{"record":{"id":"1c0f0a324ca34261","repo":"different-ai/openwork","slug":"error-sanitized-request-error","errorCode":null,"errorMessage":"${error} (sanitized request error)","messagePattern":"(.+?) \\(sanitized request error\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"ee/apps/den-api/src/observability/hono.ts","lineNumber":96,"sourceCode":"  if (error instanceof HTTPException) {\n    return new HTTPException(error.status, {\n      message: sanitizeText(error.message),\n      res: error.res,\n    })\n  }\n\n  return sanitizeExceptionForTelemetry(error)\n}\n\nexport function createTelemetryErrorSanitizerMiddleware(): MiddlewareHandler {\n  return async (c, next) => {\n    try {\n      await next()\n      if (c.error) {\n        c.error = sanitizeRequestError(c.error)\n      }\n    } catch (error) {\n      throw sanitizeRequestError(error)\n    }\n  }\n}\n\ntype ErrorResponseFactory<E extends Env> = (error: Error, c: Context<E>, requestId: string) => Response | undefined | Promise<Response | undefined>\n\nexport function registerAppErrorHandler<E extends Env>(app: Hono<E>, responseForError?: ErrorResponseFactory<E>) {\n  const logger = appLogger.child({ component: \"http\" })\n\n  app.onError(async (error, c) => {\n    const safeError = sanitizeRequestError(error)\n    const status = statusFromError(safeError)\n    const requestId = c.get(\"requestId\")\n    const fields = {\n      request_id: typeof requestId === \"string\" ? requestId : undefined,\n      http_method: c.req.method,\n      http_route: normalizedHonoRoute(c),\n      http_status_code: status,","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-api/src/observability/hono.ts#L78-L114","documentation":"createTelemetryErrorSanitizerMiddleware is a Hono middleware that wraps the downstream handler. After next() it rewrites any error set on the context, and any thrown exception, through sanitizeRequestError so that upstream request errors reaching telemetry/clients never leak internal details (URLs, headers, stack internals). It throws the sanitized error so outer handlers still see an Error.","triggerScenarios":"Any downstream route handler throws an exception, or sets c.error, while this middleware is registered; the middleware intercepts it and re-throws the sanitized version (message becomes `${error} (sanitized request error)` for unknown shapes).","commonSituations":"A fetch to an upstream provider fails with a verbose Axios/fetch error; a DB error contains connection strings; an unexpected non-Error value is thrown and gets stringified with the suffix.","solutions":["Fix the root cause of the original downstream error — the sanitized error intentionally hides detail, so check server logs/telemetry for the pre-sanitization error.","If the message looks wrong, verify the thrown value is an Error instance (not a string/object) so sanitization preserves its message.","Ensure this middleware is only applied to request-facing routes, not internal ones where full detail is needed.","If you need the raw error for debugging, log it before sanitization inside the handler."],"exampleFix":"// before\nthrow \"upstream fetch failed for https://internal.host/key\"\n// after\nthrow new Error(\"upstream fetch failed\")","handlingStrategy":"try-catch","validationCode":"if (!(value instanceof Error)) value = new Error(String(value))","typeGuard":"function isError(e: unknown): e is Error { return e instanceof Error }","tryCatchPattern":"try { await callApi() } catch (e) { logger.error('pre-sanitization', e); /* response is sanitized by middleware */ }","preventionTips":["Always throw Error instances, never strings or plain objects","Log the raw error server-side before middleware sanitization","Keep the sanitizer middleware enabled on all public routes"],"tags":["http-middleware","error-sanitization","hono"],"backgroundTag":"error-sanitization","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}