From c38f1de315abe52cb33eb553e11bd148beaccecc Mon Sep 17 00:00:00 2001 From: Noa Flaherty Date: Sun, 10 May 2026 21:23:54 -0400 Subject: [PATCH] fix(daemon): pass structured referencedBy in 409 conflict details The HTTP adapter was dropping RouteError.details when building error responses. Now passes err.details through to the standard error envelope, and the delete handler includes { referencedBy: [...] } in ConflictError details so the Swift conflict sheet can display them without fragile message-string parsing. Co-Authored-By: Claude Opus 4.6 (1M context) --- assistant/src/runtime/http-server.ts | 1 + assistant/src/runtime/routes/errors.ts | 4 ++-- .../runtime/routes/inference-provider-connection-routes.ts | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/assistant/src/runtime/http-server.ts b/assistant/src/runtime/http-server.ts index d13891cb972..7ae2b0b020c 100644 --- a/assistant/src/runtime/http-server.ts +++ b/assistant/src/runtime/http-server.ts @@ -630,6 +630,7 @@ export class RuntimeHttpServer { err.code as HttpErrorCode, err.message, err.statusCode, + err.details, ); } throw err; diff --git a/assistant/src/runtime/routes/errors.ts b/assistant/src/runtime/routes/errors.ts index 9e6d7570d79..c2a9b3bb342 100644 --- a/assistant/src/runtime/routes/errors.ts +++ b/assistant/src/runtime/routes/errors.ts @@ -77,8 +77,8 @@ export class UnprocessableEntityError extends RouteError { } export class ConflictError extends RouteError { - constructor(message: string) { - super(message, "CONFLICT", 409); + constructor(message: string, details?: unknown) { + super(message, "CONFLICT", 409, details); this.name = "ConflictError"; } } diff --git a/assistant/src/runtime/routes/inference-provider-connection-routes.ts b/assistant/src/runtime/routes/inference-provider-connection-routes.ts index aabbf1f4c04..5ef373f573d 100644 --- a/assistant/src/runtime/routes/inference-provider-connection-routes.ts +++ b/assistant/src/runtime/routes/inference-provider-connection-routes.ts @@ -135,6 +135,7 @@ function handleDeleteConnection({ pathParams = {} }: RouteHandlerArgs) { if ((config.llm?.default as Record | undefined)?.provider_connection === name) { throw new ConflictError( `Connection "${name}" is referenced by llm.default. Update llm.default.provider_connection before deleting.`, + { referencedBy: ["llm.default"] }, ); } @@ -155,6 +156,7 @@ function handleDeleteConnection({ pathParams = {} }: RouteHandlerArgs) { if (result.error.code === "has_references") { throw new ConflictError( `Connection "${name}" is referenced by ${result.error.count} profile(s): ${referencingProfiles.join(", ")}.`, + { referencedBy: referencingProfiles }, ); } throw new BadRequestError("Delete failed.");