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
- Log/inspect the raw payload to see the actual shape and compare with {items:[]}.
- Update the client check if the server moved to a bare-array response (Array.isArray(value) branch).
- Align server and den-web versions.
- 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
- Validate the runs endpoint contract with a Zod schema at the boundary, not ad-hoc checks.
- Add contract tests asserting {items:[...]} for the runs endpoint.
- Keep automationRunSchema in sync with server run fields.
- Log the offending payload when this error fires to catch envelope changes early.
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
- Profile update response did not include a user.
- Automation run response was invalid.
- Automation cancellation response was invalid.
- Connection details were missing from the worker response.
- Den returned an invalid diagnostics configuration response.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/7f50a550cf087861.
Report an issue: GitHub.