Egonex-AI/Understand-Anything · warning · Error

Freshness response was malformed

Error message

Freshness response was malformed

What it means

Thrown by requestFreshnessReport after a successful HTTP response whose JSON body fails the isDashboardFreshnessReport structural guard. The guard verifies a graphs object with a valid knowledge GraphFreshnessResult and an optional domain result, each of which must match one of the status variants (fresh/dirty/stale/unknown) with consistent counts and hashes.

Source

Thrown at understand-anything-plugin/packages/dashboard/src/freshness.ts:177

export function shouldRequestFreshness(
  demoMode: boolean,
  demoFreshnessUrl?: string,
): boolean {
  return !demoMode || Boolean(demoFreshnessUrl);
}

export async function requestFreshnessReport(
  url: string,
  signal: AbortSignal,
  fetcher: typeof fetch = fetch,
): Promise<DashboardFreshnessReport> {
  const response = await fetcher(url, { signal, cache: "no-store" });
  if (!response.ok) throw new Error("Freshness request failed");

  const payload: unknown = await response.json();
  if (!isDashboardFreshnessReport(payload)) {
    throw new Error("Freshness response was malformed");
  }
  return payload;
}

interface FreshnessRefreshOptions {
  target: Pick<EventTarget, "addEventListener" | "removeEventListener">;
  load: (signal: AbortSignal) => Promise<DashboardFreshnessReport>;
  onResult: (report: DashboardFreshnessReport) => void;
}

function requestFailedReport(): DashboardFreshnessReport {
  return {
    graphs: {
      knowledge: {
        status: "unknown",
        reason: "freshness-request-failed",
      },
    },

View on GitHub (pinned to 32944829e7)

Solutions

  1. Confirm the dashboard dev server version matches the client expecting this freshness schema.
  2. Inspect the actual response body to find which field the isDashboardFreshnessReport guard rejects (status string, count consistency, hash format, relation).
  3. Ensure the freshness endpoint returns a complete DashboardFreshnessReport with valid knowledge (and optional domain) results.
  4. Handle the error and fall back to the degraded 'unknown' report, as startFreshnessRefresh does.

Example fix

// before
const report = await requestFreshnessReport(url, signal);
// after — guard then degrade
import { isDashboardFreshnessReport } from './freshness';
const payload = await (await fetch(url)).json();
const report = isDashboardFreshnessReport(payload) ? payload : { graphs: { knowledge: { status: 'unknown', reason: 'freshness-request-failed' } } };
Defensive patterns

Strategy: type-guard

Validate before calling

import { isDashboardFreshnessReport } from './freshness';
const payload = await (await fetch(url)).json();
if (!isDashboardFreshnessReport(payload)) { /* use degraded report instead of throwing */ }

Type guard

import { isDashboardFreshnessReport, type DashboardFreshnessReport } from './freshness';
// isDashboardFreshnessReport is the exported type guard:
// (value: unknown) => value is DashboardFreshnessReport

Try / catch

let report: DashboardFreshnessReport;
try { report = await requestFreshnessReport(url, signal); }
catch (e) { report = { graphs: { knowledge: { status: 'unknown', reason: 'freshness-request-failed' } } }; }

Prevention

When it happens

Trigger: The freshness endpoint returns 200 but the body is not the expected shape: missing graphs, a knowledge result with an unknown status string, mismatched changedFileCount vs changedFiles.length, a non-hash graphCommitHash, or a stale result lacking a valid relation. Also fires on an unrelated 200 response (e.g. an HTML page from a misrouted proxy).

Common situations: Tool/dashboard version skew where the server emits a newer or older freshness schema; a proxy intercepting and returning a different 200 body; a half-deployed backend; a hand-crafted freshness endpoint that omits required fields.

Understand the failure class

Related errors


AI-assisted analysis of Egonex-AI/Understand-Anything@32944829e7 (2026-08-12). Data as JSON: /api/errors/945ab2ecb34afa44. Report an issue: GitHub.