Skip to content

Commit a4cdfa0

Browse files
committed
Harden Copilot error and VFS handling
1 parent 0e78b14 commit a4cdfa0

2 files changed

Lines changed: 39 additions & 5 deletions

File tree

apps/sim/lib/copilot/application/error.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,27 @@ export function messageForCopilotApplicationError(
2020
if (classified && classified.code !== 'internal') {
2121
return classified.message
2222
}
23-
trace.getActiveSpan()?.recordException(toError(error))
23+
trace.getActiveSpan()?.recordException(flattenErrorChain(error))
2424
return fallback
2525
}
26+
27+
/**
28+
* Wrapper errors (Drizzle's "Failed query: <sql>") bury the actionable cause —
29+
* the Postgres constraint/violation — in `cause`. Join the chain so the span
30+
* exception carries the part an investigator actually needs.
31+
*/
32+
function flattenErrorChain(error: unknown): Error {
33+
const primary = toError(error)
34+
const parts = [primary.message]
35+
let cursor: unknown = primary.cause
36+
let depth = 0
37+
while (cursor && depth < 4) {
38+
parts.push(toError(cursor).message)
39+
cursor = toError(cursor).cause
40+
depth += 1
41+
}
42+
if (parts.length === 1) return primary
43+
const flattened = new Error(parts.join(' ← '))
44+
flattened.stack = primary.stack
45+
return flattened
46+
}

apps/sim/lib/copilot/vfs/workspace-vfs.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1806,11 +1806,24 @@ export class WorkspaceVFS {
18061806
})
18071807
}
18081808

1809+
// deployment.json exists for EVERY workflow: "is it deployed?" is a
1810+
// question with an answer either way, and a not-found error here was a
1811+
// recurring red herring — agents probing an undeployed workflow read a
1812+
// failure instead of the fact. Versions stay gated: they genuinely
1813+
// don't exist before the first deploy.
1814+
this.registerLazy(`${prefix}deployment.json`, async () => {
1815+
if (!versionedWorkflowIds.has(wf.id)) {
1816+
return JSON.stringify({
1817+
deployed: false,
1818+
note: 'This workflow has never been deployed.',
1819+
})
1820+
}
1821+
const deploymentData = await this.loadDeployments(wf.id)
1822+
return deploymentData
1823+
? serializeDeployments(deploymentData)
1824+
: JSON.stringify({ deployed: false, note: 'This workflow has never been deployed.' })
1825+
})
18091826
if (versionedWorkflowIds.has(wf.id)) {
1810-
this.registerLazy(`${prefix}deployment.json`, async () => {
1811-
const deploymentData = await this.loadDeployments(wf.id)
1812-
return deploymentData ? serializeDeployments(deploymentData) : null
1813-
})
18141827
this.registerLazy(`${prefix}versions.json`, async () => {
18151828
const deploymentData = await this.loadDeployments(wf.id)
18161829
return deploymentData?.versions && deploymentData.versions.length > 0

0 commit comments

Comments
 (0)