{"record":{"id":"d695be4dc5a1a00c","repo":"JuliusBrussee/caveman","slug":"cave-eve-usage-missing","errorCode":"cave_eve_usage_missing","errorMessage":"cave_eve_usage_missing","messagePattern":"cave_eve_usage_missing","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/agent/src/adapters.ts","lineNumber":433,"sourceCode":"  }, reasoningRequired, \"cave_mastra_usage_missing\");\n}\n\nfunction usageFromEveEvents(events: unknown[], reasoningRequired: boolean): NormalizedUsage {\n  let totalInputTokens = 0;\n  let outputTokens = 0;\n  let cacheReadTokens = 0;\n  let cacheWriteTokens = 0;\n  let steps = 0;\n  for (const event of events) {\n    if (!isRecord(event) || event.type !== \"step.completed\" || !isRecord(event.data)) continue;\n    const usage = record(event.data.usage, \"cave_eve_usage_missing\");\n    totalInputTokens += strictInteger(usage.inputTokens, \"cave_eve_usage_missing\");\n    outputTokens += strictInteger(usage.outputTokens, \"cave_eve_usage_missing\");\n    cacheReadTokens += strictInteger(usage.cacheReadTokens, \"cave_eve_usage_missing\");\n    cacheWriteTokens += strictInteger(usage.cacheWriteTokens, \"cave_eve_usage_missing\");\n    steps++;\n  }\n  if (steps === 0 || reasoningRequired) throw new Error(\"cave_eve_usage_missing\");\n  if (cacheReadTokens + cacheWriteTokens > totalInputTokens) {\n    throw new Error(\"cave_eve_usage_missing\");\n  }\n  const inputTokens = totalInputTokens - cacheReadTokens - cacheWriteTokens;\n  return normalizeUsage({\n    inputTokens,\n    outputTokens,\n    cacheReadTokens,\n    cacheWriteTokens,\n    reasoningTokens: 0,\n    totalTokens: inputTokens + outputTokens + cacheReadTokens + cacheWriteTokens,\n  }, false, \"cave_eve_usage_missing\");\n}\n\nfunction normalizeUsage(\n  value: Record<keyof NormalizedUsage, unknown>,\n  reasoningRequired: boolean,\n  error: string,","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/27d5a3981a347890211bb1bf2439e5c821a63bc9/packages/agent/src/adapters.ts#L415-L451","documentation":"Returned by ValidateTenantSchema when the catalog query listing tenant tables and their RLS attributes (NOT NULL organization_id, relrowsecurity, relforcerowsecurity, policy existence/permissiveness/command) fails. The tables slice is a core input to the isolation checks, so a failure here aborts validation entirely. Causes are query-level: lost connection inside the read-only transaction, permission denied on pg_catalog columns, or a server whose catalog shape differs from what the query selects.","triggerScenarios":"The inspector role lacking SELECT on pg_class/pg_namespace attributes joined with pg_policy; connection dropping inside the open transaction; running against a Postgres version or a wrapper (CockroachDB, Yugabyte) with different catalog columns.","commonSituations":"Hardening the validation role too far and losing catalog read access; network flaps during long startup sequences; pointing validation at a non-vanilla Postgres compatible server.","solutions":["Read the wrapped driver error: permission denied -> grant catalog read (pg_read_all_data or explicit grants on pg_catalog relations); connection reset -> fix network/keepalive and retry validation","Confirm the target is vanilla Postgres the catalog queries were written for","Re-run the inspection SQL by hand inside a READ ONLY REPEATABLE READ transaction as the same role to reproduce","Retry ValidateTenantSchema with backoff at startup for transient failures"],"exampleFix":"-- reproduce as the validation role\nBEGIN TRANSACTION READ ONLY ISOLATION LEVEL REPEATABLE READ;\nSELECT c.relname, c.relrowsecurity, c.relforcerowsecurity\nFROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\nWHERE n.nspname = 'public';\nROLLBACK;","handlingStrategy":"try-catch","validationCode":"// Verify catalog readability as the validation role before startup validation:\nfunc preflightCatalogRead(ctx context.Context, conn *pgx.Conn) error {\n    rows, err := conn.Query(ctx, `\n        SELECT c.relname, c.relrowsecurity, c.relforcerowsecurity\n          FROM pg_catalog.pg_class c\n          JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n         WHERE n.nspname = 'public' LIMIT 1`)\n    if err != nil {\n        return fmt.Errorf(\"catalog read denied; grant pg_read_all_data or pg_catalog grants: %w\", err)\n    }\n    rows.Close()\n    return nil\n}","typeGuard":"func isInspectTablesErr(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"postgres: inspect tenant tables\")\n}\n\nfunc isPermissionDenied(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"permission denied\")\n}","tryCatchPattern":"err := postgresconfig.ValidateTenantSchema(ctx, pool)\nif isInspectTablesErr(err) {\n    switch {\n    case isPermissionDenied(errors.Unwrap(err)):\n        return fmt.Errorf(\"grant catalog read to the validation role: %w\", err) // fix grants, do not retry\n    case errors.Is(errors.Unwrap(err), context.DeadlineExceeded), isNetErr(errors.Unwrap(err)):\n        err = retryValidation(ctx, pool, 3) // transient: retry\n    }\n}\nif err != nil { return err }","preventionTips":["Grant the validation role pg_read_all_data (or explicit pg_catalog grants) in provisioning scripts","Pin deployments to vanilla Postgres versions the catalog queries are written against","Retry validation with backoff for network-class failures; never retry permission errors","Keep the startup context timeout generous enough for catalog reads on loaded servers"],"tags":["postgres","catalog","schema-validation","permissions"],"backgroundTag":null,"analyzedSha":"27d5a3981a347890211bb1bf2439e5c821a63bc9","analyzedAt":"2026-08-15T09:26:11.751Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}