{"record":{"id":"c9cdfd55ca4a39d9","repo":"windmill-labs/windmill","slug":"variable-at-path-path-already-exists-delete-it","errorCode":null,"errorMessage":"Variable at path ${path} already exists. Delete it or pick another path.","messagePattern":"Variable at path (.+?) already exists\\. Delete it or pick another path\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/mcp/secretVariable.ts","lineNumber":52,"sourceCode":"\tresourcePath: string\n\tisOauth?: boolean\n\taccount?: number\n}): Promise<void> {\n\tconst { workspace, path, value, resourcePath, isOauth, account } = args\n\tconst description = mcpTokenDescription(resourcePath)\n\n\t// The path picker rejects an occupied path, but it validates on a debounce and\n\t// this runs on the click: without the check, a fast save would rotate the token\n\t// of the connection already living there and only then fail to create its\n\t// resource, leaving that server holding a credential meant for another one.\n\tif (await ResourceService.existsResource({ workspace, path: resourcePath })) {\n\t\tthrow new Error(`A connection already exists at ${resourcePath}. Pick another path.`)\n\t}\n\n\tif (await VariableService.existsVariable({ workspace, path })) {\n\t\tconst current = await VariableService.getVariable({ workspace, path, decryptSecret: false })\n\t\tif (current.description !== description) {\n\t\t\tthrow new Error(`Variable at path ${path} already exists. Delete it or pick another path.`)\n\t\t}\n\t\tif (!isOauth) {\n\t\t\t// `is_secret` is inherited from the row when omitted, so it is restated\n\t\t\t// rather than assumed.\n\t\t\tawait VariableService.updateVariable({\n\t\t\t\tworkspace,\n\t\t\t\tpath,\n\t\t\t\trequestBody: { value, is_secret: true }\n\t\t\t})\n\t\t\treturn\n\t\t}\n\t\tawait VariableService.deleteVariable({ workspace, path })\n\t}\n\n\tawait VariableService.createVariable({\n\t\tworkspace,\n\t\trequestBody: { path, value, is_secret: true, is_oauth: isOauth, account, description }\n\t})","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/mcp/secretVariable.ts#L34-L70","documentation":"The MCP secret-variable store keeps a variable at `path`; if it exists with a different description than the one being saved, the code cannot tell whether it is the same connection's variable and throws rather than overwriting unrelated data. Same description means it is the same connection and the save proceeds (update/rotate).","triggerScenarios":"Saving a connection whose variable path collides with an existing variable that has a different description — i.e. the path belongs to a different connection.","commonSituations":"Renaming a connection without changing its description; reusing a variable path chosen earlier for another integration; imported config pointing at an existing variable path.","solutions":["Choose a new variable `path` for this connection.","Or delete the existing variable (and its connection) if it is obsolete, then save.","If it IS the same connection, ensure the description matches the existing one so the upsert path continues.","List variables in the workspace to identify the occupier before saving."],"exampleFix":"// before\nawait upsertSecretVariable({ workspace, path: 'mcp_secret', description: 'conn A', ... })\n// after\nawait upsertSecretVariable({ workspace, path: 'mcp_secret_conn_a', description: 'conn A', ... })","handlingStrategy":"validation","validationCode":"const exists = await VariableService.existsVariable({ workspace, path })\nif (exists) {\n  const cur = await VariableService.getVariable({ workspace, path, decryptSecret: false })\n  if (cur.description !== description) alert('Variable path belongs to another connection')\n}","typeGuard":null,"tryCatchPattern":"try { await upsertSecretVariable(args) } catch (e) { if (String(e.message).includes('Variable at path')) promptNewVariablePath(); else throw e }","preventionTips":["Derive variable paths from the connection name so description and path stay consistent","Never reuse a variable path across connections","List existing variables before choosing a path for a new connection"],"tags":["mcp","variable","path-conflict"],"backgroundTag":"variable-path-already-exists","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}