Stirling-Tools/Stirling-PDF · warning · SystemExit

Unexpected JSON structure (expected an object at root).

Error message

Unexpected JSON structure (expected an object at root).

What it means

SystemExit raised by analyze_pdf_json.py when the parsed JSON root is not an object (dict). The analyzer expects a Stirling PDF JSON export whose root is an object containing keys like fonts, pages, metadata. A JSON array, primitive, or malformed export at the root fails this check.

Source

Thrown at scripts/analyze_pdf_json.py:221

def main() -> None:
    parser = argparse.ArgumentParser(description="Inspect a PDF JSON export.")
    parser.add_argument("json_path", type=Path, help="Path to the JSON export.")
    args = parser.parse_args()

    json_path = args.json_path
    if not json_path.exists():
        raise SystemExit(f"File not found: {json_path}")

    file_size = json_path.stat().st_size
    print(f"File: {json_path}")
    print(f"Size: {human_bytes(file_size)} ({file_size:,} bytes)")

    with json_path.open("r", encoding="utf-8") as handle:
        document = json.load(handle)

    if not isinstance(document, dict):
        raise SystemExit("Unexpected JSON structure (expected an object at root).")

    summary = analyze_document(document, file_size)
    page_stats = summary.pages
    print(f"Pages: {page_stats.page_count}")
    print(f"Total text elements: {page_stats.total_text_elements:,}")
    print(f"Total image elements: {page_stats.total_image_elements:,}")
    print(
        f"Page structural bytes (text arrays + images + streams + annotations): "
        f"{human_bytes(page_stats.text_struct_bytes + page_stats.image_struct_bytes + page_stats.content_stream_bytes + page_stats.annotations_bytes)}"
    )

    font_stats = summary.fonts
    print("\nFont summary:")
    print(f"  Fonts total: {font_stats.total}")
    print(f"  Fonts with cosDictionary: {font_stats.with_cos}")
    print(f"  Fonts with program: {font_stats.with_program}")
    print(f"  Fonts with webProgram: {font_stats.with_web_program}")
    print(f"  Fonts with pdfProgram: {font_stats.with_pdf_program}")

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Confirm the file is a Stirling PDF text-editor JSON export (should have top-level 'pages', 'fonts', 'metadata').
  2. Re-export the PDF from the editor.
  3. Inspect the file root with: python -c "import json;print(type(json.load(open('file.json'))))".
Defensive patterns

Strategy: validation

Validate before calling

# Confirm the root is an object with expected keys before analysis
if not isinstance(document, dict) or not {"pages", "fonts"} <= document.keys():
    raise SystemExit("Not a Stirling PDF JSON export (missing pages/fonts at root).")

Type guard

def is_pdf_export(document: object) -> bool:
    return isinstance(document, dict) and "pages" in document and "fonts" in document

Prevention

When it happens

Trigger: The file contains valid JSON but the root is an array (e.g. a list of pages) or a scalar, not the expected object shape. The file is a different JSON format mistaken for a PDF export.

Common situations: Pointing the analyzer at the wrong JSON file (e.g. a raw page array export, a config file). A truncated/corrupted export that parsed to a partial structure. An upstream change to the export schema.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/6320450b284b5f57. Report an issue: GitHub.