> For the complete documentation index, see [llms.txt](https://developer.frontitude.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.frontitude.com/developer-cli/errors.md).

# Error handling

> **Note:** The `--error-format` flag is available from CLI version 1.5.0 and above.

Every command exits with a status code your shell or CI pipeline can check:

| Exit code | Meaning                                                                                                                                                                                                                   |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0`       | Success. The command completed, a dry-run preview was shown, or an interactive prompt was declined. For `push --update`, also when `--on-conflict=skip` skipped conflicts.                                                |
| `1`       | Failure. See the error message for details. For `push --update`, also a conflict with `--on-conflict=fail` (also in a dry run), a failed chunk, a lock file that was not saved, or a server that does not support update. |

## Error format

By default, errors are printed as a human-readable message, switching to `json` automatically when `CI=true` is set. That way CI pipelines, scripts, and AI agents get a machine-readable object without extra configuration. You can also request it explicitly with `--error-format json` (or set `FRONTITUDE_ERROR_FORMAT=json`):

```bash
$ frontitude pull --error-format json
{"error":{"code":"UNAUTHENTICATED","message":"Your access token is missing or invalid."}}
```

The object always has the shape `{ "error": { "code": string, "message": string } }`. The `code` is a stable identifier you can branch on; the `message` is a human-readable explanation when one is available.

Most failures print only this object on stdout. When `push` ends with `LOCK_NOT_SAVED` or `PUSH_PARTIALLY_APPLIED`, the preview and the summary of the work that was done come first. So do not parse the whole stdout as one JSON value. Read the last line.

## Error codes

| Code                   | Meaning                                                                                                                     |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `UNAUTHENTICATED`      | The access token is missing, invalid, or expired. Re-authenticate with `frontitude login` or pass a valid `--access-token`. |
| `FORBIDDEN`            | The authenticated user does not have access to the requested project or resource.                                           |
| `INTEGRATION_DISABLED` | The developer integration add-on is turned off for the workspace. Enable it from the workspace settings.                    |
| `VALIDATION_ERROR`     | The request was rejected because the input was invalid.                                                                     |
| `INVALID_MENTION`      | A `@mention` in a push message did not match an active workspace member.                                                    |
| `UNIQUE_KEY_EXISTS`    | One or more of the keys being pushed already exist in the workspace.                                                        |
| `LIMIT_REACHED`        | The workspace has reached its plan's text-component limit.                                                                  |
| `EXPORT_TOO_LARGE`     | The export is too large to return in a single response. Narrow the pull with filters such as `--pages` or `--tags`.         |
| `NOT_FOUND`            | The requested resource could not be found.                                                                                  |
| `INTERNAL`             | An unexpected server error occurred. Retry, and contact support if it persists.                                             |

New codes may be added over time. The accompanying `message` is a human-readable explanation when one is available.

The CLI has more codes for its own checks. See [Variable and plural format errors](#variable-and-plural-format-errors), [Multi-file output errors](#multi-file-output-errors), and [Update errors](#update-errors).

## Variable and plural format errors

These errors apply to `.json` files. On `push`, the CLI sends nothing to Frontitude. See [Variable and plural formats](/developer-cli/file-formats/web--json.md#variable-and-plural-formats).

| Code                             | Message starts with                                                    | Fix                                                                                                         |
| -------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `INVALID_FORMAT_CONFIG`          | `Invalid variableFormat "…"`                                           | Use a template with the word `name` exactly once and text before or after it, for example `%{name}`.        |
| `INVALID_FORMAT_CONFIG`          | `Invalid pluralFormat: "style" is required`                            | Add `"style": "suffix"` or `"style": "joined"`.                                                             |
| `INVALID_FORMAT_CONFIG`          | `Invalid pluralFormat: the joined style needs a non-empty "delimiter"` | Add a `delimiter` to `pluralFormat` in `frontituderc.json`. `--plural-format joined` doesn't supply one.    |
| `INVALID_FORMAT_CONFIG`          | `Invalid pluralFormat: unknown style` or `unknown plural form`         | Use `suffix` or `joined` as the style, and only `zero`, `one`, `two`, `few`, `many`, or `other` in `forms`. |
| `PLURAL_LOCALE_UNKNOWN`          | `Cannot determine the plural forms for locale`                         | Set `forms`, for example `"forms": ["one", "other"]`.                                                       |
| `JOINED_PLURAL_SEGMENT_MISMATCH` | `Joined plural values do not match the plural forms of the locale`     | Fix the values that the message lists. Or set `forms` if your forms are in another order.                   |
| `UNSUPPORTED_PUSH_FILE_SHAPE`    | `Push needs flat string values`                                        | The file came from `pull --nested` or `pull --include-metadata`. Pull without those flags.                  |
| `JSON_PLURAL_SUFFIX_COLLISION`   | `Ambiguous JSON keys`                                                  | Rename one of the keys that the message lists, for example `menu.items` and `menu.items.one`.               |

## Multi-file output errors

These errors apply when `filePath` uses `{prefix}`. `INVALID_TAGS_CONFIG` and the Android XML `INVALID_STRINGS_FILE` also apply without it. When one of them stops a command, `pull` writes nothing and `push` sends nothing. See [One file per key prefix](/developer-cli/file-formats/web--json.md#one-file-per-key-prefix). In the messages, `<…>` stands for a value from your files or settings.

| Code                            | Message                                                                                                                         | Fix                                                                                                                                                                                                                                                                                             |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `MULTI_FILE_UNSUPPORTED_OPTION` | `--nested cannot be used when filePath uses {prefix}. Multi-file output writes flat JSON only.` Also with `--include-metadata`. | Run `pull` without the flag.                                                                                                                                                                                                                                                                    |
| `LOCALE_TOKEN_REQUIRED`         | `--include-translations needs {locale} in filePath when filePath uses {prefix}, …`                                              | Add `{locale}` to every pattern, to `fallbackFilePath` and to `newFilePath`. Or pull without `--include-translations`.                                                                                                                                                                          |
| `SOURCE_LANGUAGE_NOT_SET`       | `filePath uses {locale}, but your Frontitude workspace has no source language. …`                                               | Set a source language in the workspace settings, or remove `{locale}`.                                                                                                                                                                                                                          |
| `DUPLICATE_PREFIX_FILE`         | `Two files match the prefix "<prefix>": <path A> and <path B>. …`                                                               | Rename or remove one file, or make `filePath` narrower.                                                                                                                                                                                                                                         |
| `DUPLICATE_KEY_ACROSS_FILES`    | `These keys appear in more than one strings file. …`, then one line per key with both files, up to five keys.                   | Keep each key in one file only, then push again.                                                                                                                                                                                                                                                |
| `NO_STRINGS_FILES_FOUND`        | `No strings files match filePath, and fallbackFilePath does not exist. Nothing to push.`                                        | Check that `filePath` matches your files. A file that cannot be a key prefix is skipped.                                                                                                                                                                                                        |
| `INVALID_TAGS_CONFIG`           | `Invalid tags in frontituderc.json: …`                                                                                          | Use a list of tag names, such as `["web-admin"]`, or one comma-separated string.                                                                                                                                                                                                                |
| `INVALID_STRINGS_FILE`          | `<file> is not valid JSON: <detail>`                                                                                            | Fix the JSON in the file.                                                                                                                                                                                                                                                                       |
| `INVALID_STRINGS_FILE`          | `<file> must contain a JSON object such as {"Checkout.title": "Add"}, …`                                                        | Change the file to one JSON object, or `{}`.                                                                                                                                                                                                                                                    |
| `INVALID_STRINGS_FILE`          | `<file> must hold text values only, but these keys do not: …` (up to five keys)                                                 | The pattern probably matched a file that is not a strings file. Make `filePath` narrower, or change the values to text.                                                                                                                                                                         |
| `INVALID_STRINGS_FILE`          | `The strings files changed while pull was running. Nothing was written. Run pull again.`                                        | Run `pull` again, and don't change the files while it runs.                                                                                                                                                                                                                                     |
| `INVALID_STRINGS_FILE`          | `<file> has <element>. Pull can keep only <string> elements and <plurals> elements with items in this file, …`                  | An Android XML file has another element, such as `<string-array>`, or a `<plurals>` without items. Move it to a resource file that Frontitude does not manage, for example `res/values/arrays.xml`. See [Android XML](/developer-cli/file-formats/android-xml-.xml.md#pull-and-other-elements). |

### Invalid routing settings

These messages all have the code `INVALID_ROUTING_CONFIG`. `<p>` is the value you wrote. Messages marked "(all three)" also exist for `newFilePath` and `fallbackFilePath`.

| Message starts with                                                                                                                                                                              | Fix                                                                                               |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- |
| `Invalid filePath "<p>": {prefix} must appear once, in the file name`                                                                                                                            | Use `{prefix}` once, in the file name.                                                            |
| `Invalid filePath "<p>": "**" must be a whole path segment`                                                                                                                                      | Write `**` as a whole folder name, such as `src/**/strings`, and not as the file name.            |
| `Invalid filePath "<p>": "*" cannot share a path segment with {prefix} or {locale}`                                                                                                              | Don't put `*` in a name that has `{prefix}` or `{locale}`.                                        |
| `Invalid filePath "<p>": paths must be relative to frontituderc.json` (all three)                                                                                                                | Use a relative path without `..`.                                                                 |
| `Invalid filePath "<p>": remove the empty or "." path segment` (all three)                                                                                                                       | Remove the `//` or the `.` segment in the middle of the path.                                     |
| `Invalid filePath "<p>": multi-file output supports .json files only`                                                                                                                            | Use a file name that ends with `.json`.                                                           |
| `Invalid filePath "<p>": unknown token "<t>"` (all three)                                                                                                                                        | Fix the spelling. The only tokens are `{prefix}` and `{locale}`, in lower case.                   |
| `Invalid filePath "<p>": wildcards and {locale} need {prefix} in the same pattern`                                                                                                               | Add `{prefix}` to the file name, or remove the wildcards and `{locale}`.                          |
| `Invalid filePath: a list needs at least one pattern`                                                                                                                                            | Put `{prefix}` in every pattern of the list.                                                      |
| `Invalid filePath: use a path string, or a list of path strings`                                                                                                                                 | Change `filePath` to a string or a list of strings.                                               |
| `Invalid filePath: use {locale} in every pattern or in none`                                                                                                                                     | Add `{locale}` to every pattern of the list, or remove it from all.                               |
| `fallbackFilePath is required when filePath uses {prefix}`                                                                                                                                       | Add `fallbackFilePath`.                                                                           |
| `Invalid fallbackFilePath "<p>": use a .json path without wildcards or {prefix}`                                                                                                                 | Use one `.json` path without `*`, `**`, or `{prefix}`.                                            |
| `Invalid fallbackFilePath "<p>": it must contain {locale} because filePath does`, the same for `newFilePath`, or `Invalid <setting> "<p>": it cannot contain {locale} because filePath does not` | Use `{locale}` in `filePath`, `newFilePath`, and `fallbackFilePath` together, or in none of them. |
| `Invalid fallbackFilePath "<p>": it matches the filePath pattern "<pattern>"`                                                                                                                    | Move the fallback file outside the `filePath` patterns.                                           |
| `Invalid fallbackFilePath "<p>": with the locale id "<id>" it points to "<path>", outside the project folder`                                                                                    | Check the path and the locale ids of your workspace.                                              |
| `Invalid newFilePath "<p>": use {prefix} once in the file name and no wildcards`                                                                                                                 | Use `{prefix}` once in the file name, without `*` or `**`.                                        |
| `Invalid newFilePath "<p>": the files it creates would not match any filePath pattern`                                                                                                           | Change `newFilePath` so that a `filePath` pattern matches the files it creates.                   |

## Update errors

These errors come from `push --update` and from lock files. `TRANSLATION_PATH_IS_SOURCE` also stops `pull --include-translations`. Except for `PUSH_PARTIALLY_APPLIED`, `LOCK_NOT_SAVED` and `SERVER_UPDATE_UNSUPPORTED`, `push` writes nothing in Frontitude when one of them stops it. See [Update existing keys](/developer-cli/commands.md#update-existing-keys). In the messages, `<…>` stands for a value from your files or settings.

| Code                         | Message starts with                                                                                                         | Fix                                                                                                                                                                                                                                                                                                                                                                          |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `UPDATE_REQUIRED`            | `--on-conflict needs --update.`, `--include-translations needs --update.` or `--rename and --apply-renames need --update.`  | Add `--update`, or remove the flag.                                                                                                                                                                                                                                                                                                                                          |
| `INVALID_PUSH_CONFIG`        | `Invalid <setting> in frontituderc.json: use <values>.`                                                                     | Use one of the values that the message lists.                                                                                                                                                                                                                                                                                                                                |
| `SERVER_UPDATE_UNSUPPORTED`  | `This Frontitude server does not support update.`                                                                           | Push without `--update`. A run that cannot ask may already have created the new keys. Use `--dry-run` first.                                                                                                                                                                                                                                                                 |
| `PUSH_CONFLICTS`             | `The push stopped because of conflicts, and --on-conflict=fail is set. Nothing was written.`                                | Resolve the conflicts that push lists on stderr. See [Conflicts](/developer-cli/commands.md#conflicts).                                                                                                                                                                                                                                                                      |
| `PUSH_PARTIALLY_APPLIED`     | `Chunk <n> of <total> was not applied: <reason>`                                                                            | The message says how many chunks were applied and how many keys were not pushed. Run the same command again. The saved keys are then unchanged.                                                                                                                                                                                                                              |
| `LOCK_NOT_SAVED`             | `The push succeeded, but the lock file <path> was not saved: <reason>.`                                                     | Fix the problem and run `push --update` again. Push sees that both sides agree, and nothing is lost.                                                                                                                                                                                                                                                                         |
| `LOCK_FILE_INVALID`          | `Cannot use the lock file <path>: <reason>.`                                                                                | If the file has a git merge conflict, resolve the merge. Otherwise delete the lock file, but read [Lock files](/developer-cli/commands.md#lock-files) first.                                                                                                                                                                                                                 |
| `LOCK_FILE_VERSION`          | `The lock file <path> has version <n>, but this CLI reads version 1.`                                                       | Upgrade the CLI.                                                                                                                                                                                                                                                                                                                                                             |
| `LOCK_FILE_LOCALE`           | `The lock file <path> is for locale "<a>", but this strings file is for locale "<b>".`                                      | Restore the right lock file, or delete this one to start over.                                                                                                                                                                                                                                                                                                               |
| `INVALID_RENAME`             | `--rename <value> …`                                                                                                        | The message says what is wrong: the value is not `old=new` (a key that contains `=` cannot be renamed this way), the two keys are the same, a key is in more than one `--rename`, the new key is not in the strings files, the old key is still in a strings file, or the new key is already synced as its own component. See [Renames](/developer-cli/commands.md#renames). |
| `EMPTY_PUSH_VALUE`           | `These keys have an empty value.`                                                                                           | Give each key that the message names a value, or remove the key.                                                                                                                                                                                                                                                                                                             |
| `UNKNOWN_TRANSLATION_LOCALE` | `<path> has the target language "<language>", but by its name it is the translation file of the workspace locale <locale>.` | Fix the target language or the file name.                                                                                                                                                                                                                                                                                                                                    |
| `TRANSLATION_PATH_IS_SOURCE` | `The "<locale>" translation file of <path> would be the source file itself. …`                                              | Move the source file into the `.lproj` folder of the source language, or into `Base.lproj`. See [Translation paths](/developer-cli/file-formats/apple-strings-.strings.md#translation-paths).                                                                                                                                                                                |

## Warnings

A warning means the command finished but left something unchanged. Warnings go to stderr and never change the exit code. Each warning prints one summary line with the number of values, keys, prefixes, files or settings, and up to three examples. When a command fails, the warnings print before the error:

```
Warning: Variable names must use letters, digits and underscores; these tokens were left unchanged (1 value)
  e.g. {{first name}}
```

With `--error-format json`, or when `CI=true` is set, the CLI prints one JSON line instead:

```json
{"warnings":[{"code":"UNCONVERTIBLE_VARIABLE","message":"Variable names must use letters, digits and underscores; these tokens were left unchanged","count":1,"examples":["{{first name}}"]}]}
```

| Code                           | What it means                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `UNCONVERTIBLE_VARIABLE`       | A variable name has characters other than letters, digits, and underscores. The token stays unchanged.                                                                                                                                                                                                                                                      |
| `LITERAL_TOKEN`                | A value has text that looks like a variable in your `variableFormat`. `pull` wrote it as Frontitude stores it.                                                                                                                                                                                                                                              |
| `FOREIGN_TOKEN`                | A value has variable syntax of another format. The CLI left it unchanged.                                                                                                                                                                                                                                                                                   |
| `RENDER_NOT_ROUND_TRIPPABLE`   | `pull` wrote a value that would read back as different variables, for example a variable followed by letters with `:name`. Review the value.                                                                                                                                                                                                                |
| `PLURAL_DELIMITER_IN_VALUE`    | A plural form or a plain value contains your `delimiter`, so `push` would split it.                                                                                                                                                                                                                                                                         |
| `SUFFIX_KEY_AMBIGUOUS`         | A key ends in a plural form name, or clashes with a plural key. The CLI kept it as a plain key.                                                                                                                                                                                                                                                             |
| `PLURAL_FORMAT_NOT_APPLIED`    | `pluralFormat` doesn't apply to `--nested` or `--include-metadata` output. Plurals were written as Frontitude stores them.                                                                                                                                                                                                                                  |
| `IGNORED_FOR_FILE_TYPE`        | `variableFormat` and `pluralFormat` apply only to `.json` files, and your output file is another type.                                                                                                                                                                                                                                                      |
| `ROUTED_TO_FALLBACK_NO_FILE`   | A prefix has no file and `newFilePath` is not set. `pull` wrote its keys to `fallbackFilePath`. The examples are prefixes.                                                                                                                                                                                                                                  |
| `ROUTED_TO_FALLBACK_NO_PREFIX` | A key has no prefix, or a prefix that cannot be a file name. `pull` wrote it to `fallbackFilePath`. The examples are keys.                                                                                                                                                                                                                                  |
| `PREFIX_CASE_CONFLICT`         | A prefix differs only in letter case from an existing file. `pull` wrote its keys to `fallbackFilePath` and left the other file alone.                                                                                                                                                                                                                      |
| `PREFIX_FILE_SKIPPED`          | The file for a prefix would be a file that `pull` and `push` skip. `pull` wrote the keys to `fallbackFilePath`.                                                                                                                                                                                                                                             |
| `FILE_NOT_ROUTABLE`            | A file matches `filePath`, but its name cannot be a key prefix, for example `common.v2.json` with the delimiter `.`. The CLI skipped it.                                                                                                                                                                                                                    |
| `TRANSLATION_FILES_SKIPPED`    | A file looks like a single-file translation file, such as `Checkout-fr_FR.json`. The CLI skipped it. Use `{locale}` in `filePath` for translations.                                                                                                                                                                                                         |
| `KEY_IN_OTHER_FILE`            | A key is in a file that its prefix does not name. `push` sent it. The next `pull` moves it.                                                                                                                                                                                                                                                                 |
| `NON_TEXT_VALUE_SKIPPED`       | A key has no text in Frontitude. `pull` did not write it to any file.                                                                                                                                                                                                                                                                                       |
| `ROUTING_KEYS_IGNORED`         | `newFilePath` or `fallbackFilePath` is set, but `filePath` has no `{prefix}`. The CLI ignored them.                                                                                                                                                                                                                                                         |
| `LOCK_NOT_UPDATED`             | `pull --nested` and `pull --include-metadata` write files that `push` cannot read. `pull` left their lock files as they were.                                                                                                                                                                                                                               |
| `LOCK_EDITS_NOT_CHECKED`       | `push` cannot read an existing strings file. `pull` did not check it for local edits or update its lock file.                                                                                                                                                                                                                                               |
| `LOCK_READ_BACK_FAILED`        | `push` cannot read a strings file as `pull` wrote it. `pull` did not update its lock file.                                                                                                                                                                                                                                                                  |
| `APPLE_TRANSLATION_PATH_MOVED` | An Apple `.strings` translation file is only at its path from before CLI 2.0.0, so `pull` and `push` did not read or write it. The examples are `<old path> → <new path>`. Move the file to the new path, or move the source file into a `.lproj` folder. See [Translation paths](/developer-cli/file-formats/apple-strings-.strings.md#translation-paths). |
