{"record":{"id":"b0ac39d43c48911a","repo":"langgenius/dify","slug":"label-json-must-be-an-object","errorCode":null,"errorMessage":"{label} JSON must be an object.","messagePattern":"(.+?) JSON must be an object\\.","errorType":"exception","errorClass":"MigrationDataError","httpStatus":null,"severity":"error","filePath":"api/commands/data_migration.py","lineNumber":275,"sourceCode":"        )\n        with session_factory.create_session() as session:\n            result = MigrationExportService().export(selection, session=session)\n        MigrationPackageService().save_package(result.package, output_file, overwrite=overwrite)\n        click.echo(click.style(f\"Output written to {output_file}\", fg=\"green\"))\n        _print_wizard_step(\"Report\")\n        _render_report(result.report_items, context=_with_output_path(result.report_context, output_file))\n    except MigrationDataError as exc:\n        raise click.ClickException(str(exc)) from exc\n\n\ndef _load_json_object(path: str, label: str) -> dict[str, Any]:\n    try:\n        with Path(path).open(encoding=\"utf-8\") as file:\n            raw = json.load(file)\n    except json.JSONDecodeError as exc:\n        raise MigrationDataError(f\"{label} JSON is invalid: {exc.msg}\") from exc\n    if not isinstance(raw, dict):\n        raise MigrationDataError(f\"{label} JSON must be an object.\")\n    return raw\n\n\ndef _require_options(*options: tuple[str, object | None]) -> None:\n    missing_options = [name for name, value in options if value is None]\n    if missing_options:\n        raise click.UsageError(f\"Missing option(s): {', '.join(missing_options)}.\")\n\n\ndef _build_options_override(\n    package_options: ImportOptions,\n    *,\n    id_strategy: str | None,\n    conflict_strategy: str | None,\n    create_app_api_token_on_import: bool | None,\n) -> ImportOptions | None:\n    if id_strategy is None and conflict_strategy is None and create_app_api_token_on_import is None:\n        return None","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/langgenius/dify/blob/ef8544b173fd6cd7a8e71df2cab576e52bebbfbc/api/commands/data_migration.py#L257-L293","documentation":"MigrationDataError raised by _load_json_object when the file parses successfully as JSON but the top-level value is not a dict (object). The migration package and selection formats require a JSON object at the root; arrays, strings, numbers, or null are rejected.","triggerScenarios":"Triggered when the labeled JSON file is valid JSON but is an array (e.g. [{...}]), a bare scalar, or null instead of an object.","commonSituations":"The user wrapped the package in an array, exported a list of items instead of a keyed object, or pointed the option at the wrong file (e.g. a report file that is an array).","solutions":["Open the file and confirm the top-level value is an object literal `{ ... }`.","If it is an array, re-export through MigrationPackageService.save_package which writes the correct object shape.","Check that the CLI option points to the package file, not a sibling report or log.","Validate with: `python -c \"import json,sys; print(type(json.load(open(sys.argv[1]))))\" file.json` expecting <class 'dict'>."],"exampleFix":"# before - array at root\n[ { \"apps\": {...} } ]\n\n# after\n{ \"apps\": { \"ids\": [], \"all\": false } }","handlingStrategy":"type-guard","validationCode":"import json\nfrom pathlib import Path\n\ndef require_json_object(path: str, label: str) -> dict:\n    raw = json.loads(Path(path).read_text(encoding=\"utf-8\"))\n    if not isinstance(raw, dict):\n        raise SystemExit(f\"{label} must be a JSON object, got {type(raw).__name__}\")\n    return raw","typeGuard":"def is_json_object(path: str) -> bool:\n    try:\n        with Path(path).open(encoding=\"utf-8\") as f:\n            return isinstance(json.load(f), dict)\n    except (json.JSONDecodeError, OSError):\n        return False","tryCatchPattern":"try:\n    raw = _load_json_object(path, \"package\")\nexcept MigrationDataError as exc:\n    click.echo(str(exc), err=True)\n    raise click.Abort()","preventionTips":["Always export via MigrationPackageService.save_package to guarantee the object shape.","Never hand-edit the package root into an array.","Point CLI options at the package file, not at report/log arrays.","Validate the root type before invoking the wizard."],"tags":["backend","cli","data-migration","json","validation","type-mismatch"],"backgroundTag":null,"analyzedSha":"ef8544b173fd6cd7a8e71df2cab576e52bebbfbc","analyzedAt":"2026-08-12T05:15:17.394Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}