{"record":{"id":"305aab2ba5624fe2","repo":"gastownhall/beads","slug":"invalid-persistence-mode-q","errorCode":null,"errorMessage":"invalid persistence mode %q","messagePattern":"invalid persistence mode %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/types/types.go","lineNumber":959,"sourceCode":"\tPersistenceModeEphemeral,\n\tPersistenceModeNoHistory,\n}\n\n// IsValid reports whether a persistence mode is a known explicit value.\n// Empty is invalid because it would be indistinguishable from an omitted mode.\nfunc (m PersistenceMode) IsValid() bool {\n\treturn slices.Contains(validPersistenceModes, m)\n}\n\n// NormalizePersistenceMode maps a requested mode from current to its exact\n// persistence fields without mutating an issue. The returned values are\n// Ephemeral, NoHistory, and StorageClass, respectively. Plane and retention\n// changes preserve the create-selected class. Promotion clears an explicit\n// ephemeral class marker to select normalized versioned storage. An\n// unversioned record may remain persistent but cannot move to a wisp mode.\nfunc NormalizePersistenceMode(current Issue, mode PersistenceMode) (bool, bool, StorageClass, error) {\n\tif !mode.IsValid() {\n\t\treturn false, false, \"\", fmt.Errorf(\"invalid persistence mode %q\", mode)\n\t}\n\tif current.Ephemeral && current.NoHistory {\n\t\treturn false, false, \"\", fmt.Errorf(\"ephemeral and no_history are mutually exclusive\")\n\t}\n\tif !current.StorageClass.IsValid() {\n\t\treturn false, false, \"\", fmt.Errorf(\"invalid storage class %q\", current.StorageClass)\n\t}\n\twispPlane := current.Ephemeral || current.NoHistory\n\tif wispPlane && current.StorageClass != \"\" && current.StorageClass != StorageClassEphemeral {\n\t\treturn false, false, \"\", fmt.Errorf(\"storage class %q conflicts with ephemeral/no_history\", current.StorageClass)\n\t}\n\tif !wispPlane && current.StorageClass == StorageClassEphemeral {\n\t\treturn false, false, \"\", fmt.Errorf(\"storage class ephemeral requires ephemeral or no_history\")\n\t}\n\tif current.StorageClass == StorageClassUnversioned && mode != PersistenceModePersistent {\n\t\treturn false, false, \"\", fmt.Errorf(\"cannot move unversioned record to persistence mode %q\", mode)\n\t}\n\tif persistenceMode(current) == mode {","sourceCodeStart":941,"sourceCodeEnd":977,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/types/types.go#L941-L977","documentation":"NormalizePersistenceMode validates the requested PersistenceMode against the known set (persistent, ephemeral, no_history). An unrecognized string mode is rejected before any state change. This guards against typos in flags or config.","triggerScenarios":"Calling NormalizePersistenceMode(current Issue, mode) with a mode value that fails mode.IsValid() — e.g. mode \"persistant\" (typo), \"\", or an arbitrary string cast to PersistenceMode.","commonSituations":"Typo in a --persistence flag value; old config using a renamed mode value; programmatic code passing a raw string without using the PersistenceMode constants.","solutions":["Use one of the exported PersistenceMode constants instead of a raw string","Check the accepted values via PersistenceMode's IsValid/parse helpers and correct the spelling","Upgrade/align code after a mode rename in a newer library version"],"exampleFix":"// before\nNormalizePersistenceMode(issue, PersistenceMode(\"persistant\"))\n// after\nNormalizePersistenceMode(issue, PersistenceModePersistent)","handlingStrategy":"validation","validationCode":"mode := PersistenceMode(input)\nif !mode.IsValid() {\n    return fmt.Errorf(\"%q is not a valid persistence mode\", input)\n}","typeGuard":"func validPersistenceMode(s string) (PersistenceMode, bool) {\n    m := PersistenceMode(s)\n    return m, m.IsValid()\n}","tryCatchPattern":"res, err := NormalizePersistenceMode(issue, mode)\nif err != nil && strings.Contains(err.Error(), \"invalid persistence mode\") {\n    // surface valid options to the user\n}","preventionTips":["Always use exported PersistenceMode constants, never raw strings","Validate flag values with IsValid() before calling library functions","Grep configs for known typos after upgrading versions"],"tags":["persistence","validation","config"],"backgroundTag":"invalid-persistence-mode","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}