t8y2/dbx · error · RuntimeError

command returned no JSON

Error message

command returned no JSON ({' '.join(command)}):
{completed.stdout}

What it means

run_json() expects the benchmark command to emit at least one JSON object on stdout, scanning output lines from the end. If no line parses as a JSON dict it raises RuntimeError including the command and full stdout, indicating the process succeeded (exit 0) but produced unparseable or non-JSON output.

Solutions

  1. Inspect the stdout embedded in the error to see what the command actually printed
  2. Confirm the benchmark tool is the expected version that prints a JSON object to stdout
  3. Capture the output to a file and locate the JSON line; check for CRLF or non-JSON banners corrupting lines
  4. Run the command manually and verify output; add --json/--output-format flag if the tool supports one

Example fix

// before
print("bench done")  # tool prints only text -> RuntimeError: command returned no JSON
// after
print(json.dumps({"ready": True, "metrics": metrics}))  # ensure dict JSON on stdout
Defensive patterns

Strategy: try-catch

Validate before calling

def preflight_json_output(cmd: list[str], env: dict) -> None:
    probe = subprocess.run(cmd + ["--dry-run"] if supports_dry_run else cmd, env=env,
                          capture_output=True, text=True)
    if not any(_is_json_dict(line) for line in probe.stdout.splitlines()):
        raise SystemExit("tool does not emit a JSON object on stdout; check version/flags")

def _is_json_dict(line: str) -> bool:
    try:
        return isinstance(json.loads(line), dict)
    except json.JSONDecodeError:
        return False

Try / catch

try:
    result = run_json(command, environment)
except RuntimeError as e:
    print(f"no JSON produced; raw output:\n{e}")
    raise SystemExit(1)  # inspect stdout in the message for format changes

Prevention

When it happens

Trigger: The subprocess printed only human-readable logs/progress text, printed JSON to stderr instead of stdout, or emitted a JSON array/scalar (not a dict); every reversed line fails json.loads or isinstance(value, dict).

Common situations: Benchmark tool version changed its output format; a wrapper script added banner text only; JSON mixed with log lines but the dict line is last-line-first parsing missed a trailing carriage return; tool writes results to a file instead of stdout.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/ada24c3d86a40f7a. Report an issue: GitHub.

Appendix: source

Thrown at agents/drivers/iotdb/bench/run.py:127

        env=environment,
        text=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
        timeout=env_float("BENCH_COMMAND_TIMEOUT", 180.0),
    )
    if completed.returncode != 0:
        raise RuntimeError(
            f"command failed ({' '.join(command)}):\nstdout:\n{completed.stdout}\nstderr:\n{completed.stderr}"
        )
    for line in reversed(completed.stdout.splitlines()):
        try:
            value = json.loads(line)
        except json.JSONDecodeError:
            continue
        if isinstance(value, dict):
            return value
    raise RuntimeError(f"command returned no JSON ({' '.join(command)}):\n{completed.stdout}")


def measure_rss(command: list[str], environment: dict[str, str]) -> float:
    process = subprocess.Popen(
        command,
        env=environment | {"IOTDB_BENCH_MODE": "hold"},
        text=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
    )
    stderr_lines: list[str] = []

    def drain_stderr() -> None:
        assert process.stderr is not None
        stderr_lines.extend(line.rstrip() for line in process.stderr)

    threading.Thread(target=drain_stderr, daemon=True).start()
    try:

View on GitHub (pinned to c0390bff16)