bytedance/deer-flow · error

Thread history returned a row with an invalid seq.

Error message

Thread history returned a row with an invalid seq.

What it means

Thrown while validating each row of the thread history 'data' array. After confirming the payload shape, the parser checks every row's 'seq' field with isValidThreadMessageSeq. A row whose seq is missing, not a positive integer (or otherwise outside the accepted range) triggers this error, refusing to render a malformed history page.

Source

Thrown at frontend/src/core/threads/hooks.ts:355

  if (typeof value !== "object" || value === null) {
    throw new Error("Thread history returned an invalid response.");
  }

  const data = Reflect.get(value, "data");
  const hasMore = Reflect.get(value, "has_more");
  const nextBeforeSeq = Reflect.get(value, "next_before_seq");
  if (!Array.isArray(data) || typeof hasMore !== "boolean") {
    throw new Error("Thread history returned an invalid response.");
  }

  const seenSeqs = new Set<number>();
  for (const row of data) {
    const seq =
      typeof row === "object" && row !== null
        ? Reflect.get(row, "seq")
        : undefined;
    if (!isValidThreadMessageSeq(seq)) {
      throw new Error("Thread history returned a row with an invalid seq.");
    }
    if (seenSeqs.has(seq)) {
      throw new Error("Thread history returned duplicate seq values.");
    }
    seenSeqs.add(seq);
  }

  if (
    (hasMore && !isValidThreadMessageSeq(nextBeforeSeq)) ||
    (!hasMore && nextBeforeSeq !== null)
  ) {
    throw new Error(
      "Thread history returned an invalid next_before_seq cursor.",
    );
  }

  return value as ThreadMessagesPageResponse;
}

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Log one offending row (JSON.stringify) from the /messages response and check its 'seq' value.
  2. Fix the backend serializer (or fixture) so every row carries an integer seq within the valid range.
  3. If seq can legitimately be absent for some row type, filter those rows server-side instead of shipping them in the page.

Example fix

// before: row emitted without seq
{"data": [{"message_id": "m1", "content": "hi"}], "has_more": false}

// after: every row carries a valid integer seq
{"data": [{"seq": 1, "message_id": "m1", "content": "hi"}], "has_more": false, "next_before_seq": null}
Defensive patterns

Strategy: type-guard

Validate before calling

const rows = Array.isArray(body?.data) ? body.data : [];
const bad = rows.filter((r) => !(typeof r === "object" && r !== null && Number.isInteger((r as any).seq) && (r as any).seq > 0));
if (bad.length) { /* log rows, refuse to render page */ }

Type guard

function isValidSeq(seq: unknown): seq is number {
  return typeof seq === "number" && Number.isInteger(seq) && seq > 0;
}
function hasValidSeqs(rows: unknown[]): boolean {
  return rows.every((r) => typeof r === "object" && r !== null && isValidSeq(Reflect.get(r, "seq")));
}

Try / catch

catch (e) { if (e instanceof Error && e.message.includes("invalid seq")) { reportDataIssue(threadId, e); } throw e; }

Prevention

When it happens

Trigger: A row in the returned messages array is a primitive (string/number), or an object whose 'seq' is null, undefined, a non-integer, zero/negative, or a float. Happens when the backend serializer emits rows without seq (e.g. synthetic or draft messages inserted into the page) or when a float seq slips through from a DB mapping bug.

Common situations: Backend change that renames or drops the seq column in the messages payload, insertion of non-persisted placeholder messages into the history response, or a unit test fixture using {id: ...} instead of {seq: ...}.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/bc9ab1f1033f3a59. Report an issue: GitHub.