can1357/oh-my-pi · error · HindsightError

${operation} failed: ${typeof details === "string" ? details

Error message

${operation} failed: ${typeof details === "string" ? details : JSON.stringify(details)}

What it means

HindsightClient.#request converts non-OK HTTP responses into a HindsightError. It extracts a detail/message field from the parsed JSON body (or falls back to raw text) and formats `${operation} failed: <details>`, including the HTTP status code on the error object.

Source

Thrown at packages/coding-agent/src/hindsight/client.ts:574

			throw new HindsightError(message, undefined, err);
		}

		if (opts?.allow404 && response.status === 404) {
			return null as T;
		}

		const text = await response.text();
		const parsed = text ? safeJsonParse(text) : null;

		if (!response.ok) {
			const details =
				(parsed && typeof parsed === "object"
					? ((parsed as { detail?: unknown; message?: unknown }).detail ??
						(parsed as { message?: unknown }).message)
					: undefined) ??
				parsed ??
				text;
			throw new HindsightError(
				`${operation} failed: ${typeof details === "string" ? details : JSON.stringify(details)}`,
				response.status,
				details,
			);
		}

		return (parsed ?? {}) as T;
	}
}

interface BuiltMemoryItem {
	content: string;
	timestamp?: string;
	context?: string;
	metadata?: Record<string, string>;
	document_id?: string;
	tags?: string[];
	observation_scopes?: "per_tag" | "combined" | "all_combinations" | string[][];

View on GitHub (pinned to 9690622007)

Solutions

  1. Read the HindsightError status and details fields — they carry the server's own explanation
  2. Fix the request payload per the server validation message (400)
  3. Check API credentials/auth configuration (401/403)
  4. Verify client and server versions are compatible if the route 404s

Example fix

// before
await client.retain({ /* wrong shape */ });
// after
try {
  await client.retain({ content: "...", context: "..." });
} catch (err) {
  if (err instanceof HindsightError && err.status === 400) {
    console.error("Server said:", err.details);
  }
  throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// validate payload shape before sending
if (typeof body.content !== "string" || body.content.length === 0) {
  throw new Error("retain requires non-empty content");
}

Type guard

function isApiRejection(err: unknown): err is HindsightError & { status: number } {
  return err instanceof HindsightError && typeof err.status === "number";
}

Try / catch

try {
  await client.retain(payload);
} catch (err) {
  if (err instanceof HindsightError && err.status) {
    logger.error("Hindsight operation rejected", { status: err.status, details: err.details });
    if (err.status >= 500) /* retry */; else /* fix request */;
  } else throw err;
}

Prevention

When it happens

Trigger: Any Hindsight API call (retain, recall, reflect, createBank, listMemories) receiving a 4xx/5xx response: invalid request payload (400), auth failure (401/403), unknown bank (404 without allow404), or server error (500).

Common situations: Malformed retain payload rejected by server validation; expired or missing API credentials; calling an endpoint/route that doesn't exist on the deployed server version; upstream server crash.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f99a9f43cc25d36d. Report an issue: GitHub.