thedotmack/claude-mem · error

audit log insert failed

Error message

audit log insert failed

What it means

After mutating admin or queue actions, the route writes an audit record via repo.createAuditLog. The insert is best-effort: on rejection it logs this warning (with the action and requestId) and the user request still succeeds, but that action has no row in the audit log, which matters for compliance and traceability.

Source

Thrown at src/server/routes/v1/ServerV1PostgresRoutes.ts:1354

    // details win on key conflict so explicit overrides still work.
    const detailsWithRequestId: Record<string, unknown> = {
      ...(req.requestId ? { requestId: req.requestId } : {}),
      ...(details ?? {}),
    };
    const auditInput = {
      teamId: req.authContext?.teamId ?? null,
      projectId: projectId ?? req.authContext?.projectId ?? null,
      actorId,
      apiKeyId: req.authContext?.apiKeyId ?? null,
      action,
      resourceType: resolveAuditResourceType(action),
      resourceId: targetId,
      details: detailsWithRequestId,
    };
    try {
      await repo.createAuditLog(auditInput);
    } catch (error) {
      logger.warn('SYSTEM', 'audit log insert failed', {
        action,
        requestId: req.requestId ?? null,
        error: error instanceof Error ? error.message : String(error),
      });
    }
  }

  // Phase 11 — paginated job listing for team/project queue endpoints.
  // Phase 12 — extended with `sourceType`, `since`, and (optional) payload
  // selection. Filtering is enforced in SQL (WHERE team_id [, project_id,
  // status, source_type, created_at]). Application-layer filtering is never
  // trusted alone for tenant scope.
  private async listJobsForScope(input: {
    teamId: string;
    projectId: string | null;
    status: string | null;
    sourceType?: string | null;
    limit: number;

View on GitHub (pinned to e2d1df569a)

Solutions

  1. Pull the warn line's action, requestId, and error fields: the error names the exact database failure
  2. Run pending migrations so audit_logs matches createAuditLog's columns
  3. If FK targets are the cause, confirm the actor and api-key rows exist (or that nullable handling matches the schema)
  4. For transient database blips, note the audit gap and re-issue the action if a complete trail is required

Example fix

// before
await repo.createAuditLog(auditInput);

// after: retry transient failures, give up loudly after N attempts
for (let attempt = 1; attempt <= 3; attempt++) {
  try {
    await repo.createAuditLog(auditInput);
    break;
  } catch (error) {
    const transient = isPgDatabaseError(error)
      && ['57P01', '40001', '08000', '08006', '55P03'].includes(error.code);
    if (!transient || attempt === 3) {
      logger.warn('SYSTEM', 'audit log insert failed', { action, requestId, error: String(error) });
      break;
    }
    await new Promise((resolve) => setTimeout(resolve, 100 * 2 ** attempt));
  }
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-deploy check: the audit table must exist before audited routes ship
const { rows } = await pool.query("SELECT to_regclass('audit_logs') AS table_name");
if (!rows[0].table_name) throw new Error('audit_logs missing: run migrations first');

Type guard

function isPgDatabaseError(error: unknown): error is { code: string; detail?: string; message: string } {
  return typeof error === 'object' && error !== null && 'code' in error
    && typeof (error as { code: unknown }).code === 'string';
}

Try / catch

try {
  await repo.createAuditLog(auditInput);
} catch (error) {
  if (isPgDatabaseError(error) && ['08000', '08006', '40001', '55P03'].includes(error.code)) {
    // transient: retry with backoff before accepting the audit gap
  } else {
    logger.warn('SYSTEM', 'audit log insert failed', { action, requestId, error: String(error) });
  }
}

Prevention

When it happens

Trigger: Any audited v1 route call while the audit_logs insert fails: migrations not applied (missing table or columns), an FK violation for actorId or apiKeyId, a database connection blip, or schema drift between createAuditLog and the deployed table.

Common situations: Partial migrations during deploys; Postgres restart or failover mid-request; actor rows deleted between request and audit write; column type mismatches after an upgrade.

Related errors


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/929d1ad6838514ff. Report an issue: GitHub.