different-ai/openwork · error

Library response was incomplete.

Error message

Library response was incomplete.

What it means

parseLibraryPayload validates the payload returned from GET /v1/me/library before trusting it. If the payload is not a plain object or is missing an `items` array, the library item list is unusable, so it throws this error instead of returning silently-empty data. It is a defensive schema check on the server response.

Source

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

    : null;
  if (!id || (value.plugin !== null && !plugin) || !name || description === undefined || !role || !edges || !state || !resultState
    || latestSuccessfulAt === undefined || !viewState || activeViewTitle === undefined || !source
    || typeof value.automationCount !== "number" || !Number.isInteger(value.automationCount) || value.automationCount < 0) return null;
  return { type: "workflow", id, plugin, name, description, role, edges, state, resultState, latestSuccessfulAt, viewState, activeViewTitle, automationCount: value.automationCount, source };
}

function parseLibraryItem(value: unknown): LibraryItem | null {
  if (!isRecord(value)) return null;
  if (value.type === "plugin") return parsePlugin(value);
  if (value.type === "app") return null;
  if (value.type === "connection") return parseConnection(value);
  if (value.type === "workflow") return parseWorkflow(value);
  return null;
}

export function parseLibraryPayload(payload: unknown): LibraryItem[] {
  if (!isRecord(payload) || !Array.isArray(payload.items)) {
    throw new Error("Library response was incomplete.");
  }
  const items = payload.items
    .map(parseLibraryItem)
    .filter((item): item is LibraryItem => item !== null);
  const supportedItemCount = payload.items.filter((item) => !isRecord(item) || item.type !== "app").length;
  if (items.length !== supportedItemCount) {
    throw new Error("Library response was incomplete.");
  }
  return items;
}

export function useLibrary() {
  return useQuery({
    queryKey: libraryQueryKeys.items,
    queryFn: async (): Promise<LibraryItem[]> => {
      const { response, payload } = await requestJson(
        "/v1/me/library",
        { method: "GET" },

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Log the raw payload of the /v1/me/library response and confirm it is an object containing `items: []`.
  2. Check the den-api route handler for /v1/me/library to ensure it returns `{ items: [...] }` on success.
  3. Verify frontend and backend versions match (no stale deploy or mixed API versions).
  4. Inspect for proxies/interceptors (service worker, test mocks) rewriting the response body.
  5. Update the parsing function if the API contract intentionally changed.

Example fix

// before (server returning bare list)
return NextResponse.json(items);
// after (server returning expected envelope)
return NextResponse.json({ items });
Defensive patterns

Strategy: validation

Validate before calling

function isLibraryPayload(p: unknown): p is { items: unknown[] } {
  return typeof p === "object" && p !== null && !Array.isArray(p) && Array.isArray((p as { items?: unknown }).items);
}
// call: if (!isLibraryPayload(await res.json())) throw new Error("Library response was incomplete.");

Type guard

const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === "object" && v !== null && !Array.isArray(v);

Try / catch

try {
  const items = await fetchLibrary();
} catch (err) {
  if (err instanceof Error && err.message === "Library response was incomplete.") {
    console.error("Malformed /v1/me/library payload", err);
    // show empty-library fallback with a refresh action
  } else throw err;
}

Prevention

When it happens

Trigger: The /v1/me/library endpoint returns 200 but the JSON body is not an object (e.g. null, string, array) or the object lacks an `items` array property (e.g. the server returned an error-shaped body with a 200 status, a proxy stripped the body, or an API contract change renamed `items`).

Common situations: Server deployed an API version where the library payload shape changed; a gateway/CDN returned an HTML error page with status 200; the client hit a different (older/newer) backend than the one the frontend expects; response body intercepted/rewritten by middleware.

Related errors


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