different-ai/openwork · error · Error

Automation run history was invalid.

Error message

Automation run history was invalid.

What it means

useAutomationRuns fetches /v1/automations/{id}/runs via payload(), then validates that the response is an object containing an items array before parsing each item with automationRunSchema. This error is thrown when the endpoint returned 2xx but the body is not the expected {items:[...]} shape — a contract violation the client refuses to process.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/automation-data.tsx:37

export function useAutomations() {
  return useQuery({ queryKey: ["automations", "list"], queryFn: async () => automationListSchema.parse(await payload("/v1/automations?limit=100")) });
}

export function useAutomation(automationId: string | null) {
  return useQuery({
    queryKey: ["automations", "detail", automationId],
    queryFn: async () => automationDetailSchema.parse(await payload(`/v1/automations/${encodeURIComponent(automationId ?? "")}`)),
    enabled: Boolean(automationId),
  });
}

export function useAutomationRuns(automationId: string | null) {
  return useQuery({
    queryKey: ["automations", "runs", automationId],
    queryFn: async () => {
      const value = await payload(`/v1/automations/${encodeURIComponent(automationId ?? "")}/runs?limit=100`);
      if (typeof value !== "object" || value === null || !("items" in value) || !Array.isArray(value.items)) throw new Error("Automation run history was invalid.");
      return value.items.map((item) => automationRunSchema.parse(item));
    },
    enabled: Boolean(automationId),
    refetchInterval: 5_000,
  });
}

export function useAutomationRun(runId: string | null) {
  return useQuery({
    queryKey: ["automations", "run", runId],
    queryFn: async () => automationRunReceiptSchema.parse(await payload(`/v1/automation-runs/${encodeURIComponent(runId ?? "")}`)),
    enabled: Boolean(runId),
    refetchInterval: (query) => {
      const status = query.state.data?.run.status;
      return status && ["queued", "claimed", "running"].includes(status) ? 2_000 : false;
    },
  });
}

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Log/inspect the raw payload to see the actual shape and compare with {items:[]}.
  2. Update the client check if the server moved to a bare-array response (Array.isArray(value) branch).
  3. Align server and den-web versions.
  4. If items exist but individual items fail automationRunSchema.parse, the thrown Zod error names the mismatched field — fix the schema or server payload.

Example fix

// before
if (typeof value !== "object" || value === null || !("items" in value) || !Array.isArray(value.items)) throw new Error("Automation run history was invalid.");
// after
const items = Array.isArray(value) ? value : (value as { items?: unknown[] })?.items;
if (!Array.isArray(items)) throw new Error("Automation run history was invalid.");
Defensive patterns

Strategy: type-guard

Validate before calling

const value = await payload(`/v1/automations/${encodeURIComponent(automationId)}/runs?limit=100`);
if (!isRunsResponse(value)) return []; // or show error state

Type guard

function isRunsResponse(v: unknown): v is { items: unknown[] } {
  return typeof v === "object" && v !== null && "items" in v && Array.isArray((v as {items:unknown}).items);
}

Try / catch

try {
  const runs = await queryFn();
} catch (err) {
  if (err instanceof Error && err.message === "Automation run history was invalid.") {
    setRuns([]); // degraded mode: show empty history, log payload
  } else throw err;
}

Prevention

When it happens

Trigger: The runs endpoint returns null, a bare array instead of {items}, or an object without an items field; a paginated-envelope change from the server; a proxy returning an empty 200.

Common situations: Server/client version skew after the runs API changed shape; hitting an old mock server; response transformed by middleware (e.g. array unwrapping); automation deleted concurrently so the server returns an odd success body.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/7f50a550cf087861. Report an issue: GitHub.