langgenius/dify · error · MigrationDataError
{label} JSON is invalid: {exc.msg}
Error message
{label} JSON is invalid: {exc.msg} What it means
MigrationDataError raised by _load_json_object when json.load on the given path raises JSONDecodeError. The label (e.g. 'package manifest', 'selection') identifies which input file failed, and exc.msg carries the parser's position/message. The wizard's outer handler converts MigrationDataError into a click.ClickException for CLI display.
Source
Thrown at api/commands/data_migration.py:273
conflict_strategy=conflict_strategy,
output_file=output_file,
)
with session_factory.create_session() as session:
result = MigrationExportService().export(selection, session=session)
MigrationPackageService().save_package(result.package, output_file, overwrite=overwrite)
click.echo(click.style(f"Output written to {output_file}", fg="green"))
_print_wizard_step("Report")
_render_report(result.report_items, context=_with_output_path(result.report_context, output_file))
except MigrationDataError as exc:
raise click.ClickException(str(exc)) from exc
def _load_json_object(path: str, label: str) -> dict[str, Any]:
try:
with Path(path).open(encoding="utf-8") as file:
raw = json.load(file)
except json.JSONDecodeError as exc:
raise MigrationDataError(f"{label} JSON is invalid: {exc.msg}") from exc
if not isinstance(raw, dict):
raise MigrationDataError(f"{label} JSON must be an object.")
return raw
def _require_options(*options: tuple[str, object | None]) -> None:
missing_options = [name for name, value in options if value is None]
if missing_options:
raise click.UsageError(f"Missing option(s): {', '.join(missing_options)}.")
def _build_options_override(
package_options: ImportOptions,
*,
id_strategy: str | None,
conflict_strategy: str | None,
create_app_api_token_on_import: bool | None,
) -> ImportOptions | None:View on GitHub (pinned to ef8544b173)
Solutions
- Run the file through a JSON linter (e.g. `python -m json.tool path/to/file.json`) to locate the syntax error.
- Re-export or re-download the migration package to rule out truncation.
- Ensure the file is UTF-8 encoded without a leading BOM.
- Use the label in the message to identify which CLI argument's file is broken.
Example fix
# before - file has trailing comma
{
"source_tenant": {...},
}
# after
{
"source_tenant": {}
} Defensive patterns
Strategy: validation
Validate before calling
import json
from pathlib import Path
def validate_json_file(path: str) -> dict:
text = Path(path).read_text(encoding="utf-8")
try:
return json.loads(text)
except json.JSONDecodeError:
raise SystemExit(f"{path} is not valid JSON; fix with a linter first") Type guard
def is_valid_json_object(path: str) -> bool:
try:
with Path(path).open(encoding="utf-8") as f:
return isinstance(json.load(f), dict)
except (json.JSONDecodeError, OSError):
return False Try / catch
try:
payload = _load_json_object(path, "package")
except MigrationDataError as exc:
click.echo(f"Input file rejected: {exc}", err=True)
raise click.Abort() Prevention
- Run `python -m json.tool <file>` on exported packages before importing.
- Re-download packages that may have been truncated in transit.
- Save packages with UTF-8 encoding and no BOM.
- Treat the {label} in the message as the identifier of which CLI arg's file failed.
When it happens
Trigger: Triggered when the --package/--selection (or other labeled) JSON file passed to the data-migration wizard is syntactically invalid: trailing commas, unquoted keys, truncated download, BOM/encoding issues, or empty file.
Common situations: The migration package file was partially downloaded or corrupted, edited by hand with a syntax error, or saved with a non-UTF-8 encoding. The label tells you which file to re-inspect.
Related errors
- {label} JSON must be an object.
- No tenants found.
- No workflow or advanced-chat apps found for the selected ten
- usage_invalid_flag
- expected integer, got ${JSON.stringify(raw)}
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/02a687e411b4655c.
Report an issue: GitHub.