{"record":{"id":"58c7f2d95fa1b931","repo":"dagger/dagger","slug":"key-q-is-not-set-in-user-level-config-for-workspa","errorCode":null,"errorMessage":"key %q is not set in user-level config for workspace %q","messagePattern":"key %q is not set in user-level config for workspace %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/workspace/userconfig.go","lineNumber":294,"sourceCode":"}\n\n// DeleteUserConfigValue removes a config value under\n// [workspaces.<workspaceKey>] in user-level config bytes, pruning any tables\n// the removal leaves empty. It errors when the key is not set for that\n// workspace.\nfunc DeleteUserConfigValue(existing []byte, workspaceKey, key string) ([]byte, error) {\n\tparts, err := userOverlayKeyParts(key)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttree, entryKey, err := userConfigTreeAndEntryKey(existing, workspaceKey)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tfullPath := append([]string{\"workspaces\", entryKey}, parts...)\n\tif tree.GetPath(fullPath) == nil {\n\t\treturn nil, fmt.Errorf(\"key %q is not set in user-level config for workspace %q\", key, entryKey)\n\t}\n\tif err := tree.DeletePath(fullPath); err != nil {\n\t\treturn nil, fmt.Errorf(\"unset %q: %w\", key, err)\n\t}\n\t// Prune tables the removal left empty, innermost first.\n\tfor prefix := fullPath[:len(fullPath)-1]; len(prefix) > 0; prefix = prefix[:len(prefix)-1] {\n\t\tparent, ok := tree.GetPath(prefix).(*toml.Tree)\n\t\tif !ok || len(parent.Keys()) > 0 {\n\t\t\tbreak\n\t\t}\n\t\tif err := tree.DeletePath(prefix); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"prune empty table %q: %w\", strings.Join(prefix, \".\"), err)\n\t\t}\n\t}\n\n\tout, err := tree.ToTomlString()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"serialize user config: %w\", err)","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/workspace/userconfig.go#L276-L312","documentation":"DeleteUserConfigValue removes a key under [workspaces.<workspaceKey>] in user-level config and then prunes emptied tables. Before deleting, it checks tree.GetPath; if the key does not exist it throws this error instead of silently succeeding, so callers can distinguish \"removed\" from \"was never set\".","triggerScenarios":"DeleteUserConfigValue called for a key that was never written for that workspace, a typo'd key, a key belonging to a different entryKey (workspace), or after the key was already deleted in a prior call.","commonSituations":"Running an unset command twice; unsetting a key with a slightly different path than it was set with; switching workspaces (entryKey) and assuming settings carry over; concurrent edits where another process already removed the key.","solutions":["Check the key exists first with GetPath at [\"workspaces\", entryKey, ...parts] and treat nil as already-deleted","Verify the entryKey (workspace key) matches the one the value was written under","Re-run with the exact key string used at write time (segments and casing must match)","If the delete is idempotent-critical, catch this error and ignore it"],"exampleFix":"// before: unconditional delete fails on second run\nif _, err := workspace.DeleteUserConfigValue(data, key, wsKey); err != nil { return err }\n// after: tolerate not-set\nif _, err := workspace.DeleteUserConfigValue(data, key, wsKey); err != nil && !strings.Contains(err.Error(), \"is not set\") { return err }","handlingStrategy":"try-catch","validationCode":"full := append([]string{\"workspaces\", entryKey}, parts...)\nif tree.GetPath(full) == nil {\n\treturn nil // already unset; nothing to do\n}","typeGuard":null,"tryCatchPattern":"_, err := workspace.DeleteUserConfigValue(data, key, wsKey)\nif err != nil && strings.Contains(err.Error(), \"is not set\") {\n\treturn data, nil // treat as idempotent success\n}","preventionTips":["Make deletes idempotent by tolerating the not-set error","Verify the entryKey matches where the value was written","Reuse one key-builder helper for set and unset so paths always match","Check current value with GetPath before deleting in UI flows"],"tags":["go","config","user-config","unset","not-found"],"backgroundTag":"config-key-not-set","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}