coleam00/Archon · error · Error

Invalid dry-run stub file '${path}': expected one YAML mappi

Error message

Invalid dry-run stub file '${path}': expected one YAML mapping of node ids to outputs

What it means

Thrown by loadDryRunStubs when the parsed YAML is not a single mapping of node ids to outputs — i.e. it is null, not an object, or an array. Stub files must be one flat YAML object; lists or scalar documents are rejected with this guidance message.

Source

Thrown at packages/workflows/src/dry-run.ts:397

});
export type DryRunResult = z.infer<typeof dryRunResultSchema>;

export async function loadDryRunStubs(path?: string): Promise<DryRunStubs> {
  if (!path) return {};
  const file = Bun.file(path);
  if (!(await file.exists())) {
    throw new Error(`Dry-run stub file not found: ${path}`);
  }

  let parsed: unknown;
  try {
    parsed = Bun.YAML.parse(await file.text());
  } catch (error) {
    throw new Error(`Failed to parse dry-run stub file '${path}': ${(error as Error).message}`);
  }

  if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
    throw new Error(
      `Invalid dry-run stub file '${path}': expected one YAML mapping of node ids to outputs`
    );
  }
  const reservedHit = Object.keys(parsed as Record<string, unknown>).find(key =>
    RESERVED_FIXTURE_KEYS.has(key)
  );
  if (reservedHit !== undefined) {
    throw new Error(
      `Invalid dry-run stub file '${path}': contains the fixture key '${reservedHit}' — this is a fixture file; run it with 'workflow test'`
    );
  }
  const result = dryRunStubsSchema.safeParse(parsed);
  if (!result.success) {
    const issues = result.error.issues
      .map(issue => `${issue.path.join('.') || '<root>'}: ${issue.message}`)
      .join('; ');
    throw new Error(`Invalid dry-run stub file '${path}': ${issues}`);
  }

View on GitHub (pinned to 0773b97458)

Solutions

  1. Reformat the file as one top-level YAML mapping: `nodeId: <output value>` per key.
  2. Ensure the file is non-empty and not a bare list.
  3. If you meant fixture-style input, run it through `workflow test` instead of the stub loader.

Example fix

# before (list)
- summarize: { text: hi }
# after (mapping)
summarize:
  text: hi
Defensive patterns

Strategy: type-guard

Validate before calling

function isNonEmptyYamlMapping(text: string): boolean {
  if (!text.trim()) return false;
  try {
    const v = Bun.YAML.parse(text);
    return typeof v === "object" && v !== null && !Array.isArray(v);
  } catch { return false; }
}

Type guard

function isStubMapping(v: unknown): v is Record<string, unknown> {
  return typeof v === "object" && v !== null && !Array.isArray(v);
}

Try / catch

try {
  const stubs = await loadDryRunStubs(path);
} catch (err) {
  if (err instanceof Error && err.message.includes("expected one YAML mapping of node ids to outputs")) {
    console.error("Stub file must be a top-level mapping `nodeId: output`:", err.message);
  } else throw err;
}

Prevention

When it happens

Trigger: Loading a stub file whose top-level document is an array, a scalar (string/number), an empty document (parses to null), or a fixture file in a list-like shape.

Common situations: Writing `- id: foo` list-style stubs instead of a mapping, saving an empty file (parses to null), or passing a test fixture file instead of a stub file.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/6eb9791d8363c29e. Report an issue: GitHub.