{"record":{"id":"b3262ff82ca9ea8e","repo":"gastownhall/beads","slug":"read-wisp-s-w","errorCode":null,"errorMessage":"read wisp %s: %w","messagePattern":"read wisp (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/uow/issue_operations.go","lineNumber":502,"sourceCode":"func updateHistoryEntry(request publicops.UpdateRequest, changed bool) string {\n\tif !changed && request.Claim && reflect.DeepEqual(request.Patch, publicops.IssuePatch{}) {\n\t\treturn \"\"\n\t}\n\treturn storageissueops.HistoryEntry(request.Provenance, \"update issue\")\n}\n\n// operationIssue resolves id to the row an operation is about. Both planes are\n// searched unless issuePlaneOnly restricts it, in which case a wisp id is a\n// miss rather than an ephemeral row to operate on. Every call runs inside the\n// operation's own transaction.\nfunc operationIssue(ctx context.Context, uw UnitOfWork, id string, issuePlaneOnly bool) (*types.Issue, bool, error) {\n\tif !issuePlaneOnly {\n\t\tissue, err := uw.IssueUseCase().GetWisp(ctx, id)\n\t\tif err == nil && issue != nil {\n\t\t\treturn issue, true, nil\n\t\t}\n\t\tif err != nil && !errors.Is(err, publicops.ErrNotFound) && !dberrors.IsNoRows(err) {\n\t\t\treturn nil, false, fmt.Errorf(\"read wisp %s: %w\", id, err)\n\t\t}\n\t}\n\tissue, err := uw.IssueUseCase().GetIssue(ctx, id)\n\tif err != nil {\n\t\tif errors.Is(err, publicops.ErrNotFound) || dberrors.IsNoRows(err) {\n\t\t\treturn nil, false, fmt.Errorf(\"%w: issue %s\", publicops.ErrNotFound, id)\n\t\t}\n\t\treturn nil, false, err\n\t}\n\tif issue == nil {\n\t\treturn nil, false, fmt.Errorf(\"%w: issue %s\", publicops.ErrNotFound, id)\n\t}\n\treturn issue, false, nil\n}\n\nfunc validationError(err error) error {\n\tif errors.Is(err, publicops.ErrValidation) {\n\t\treturn err","sourceCodeStart":484,"sourceCodeEnd":520,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/uow/issue_operations.go#L484-L520","documentation":"operationIssue first tries the wisp plane via GetWisp; if the wisp read fails with an error that is neither ErrNotFound nor a no-rows error, the operation aborts and this error wraps the underlying failure. It signals an unexpected storage-layer failure while reading the ephemeral (wisp) copy of an issue, not a simple 'does not exist' case.","triggerScenarios":"Calling Update/Close/Reopen/hydrateIssueOperation when issuePlaneOnly is false and uw.IssueUseCase().GetWisp returns a genuine error (DB corruption, connection failure, driver error) rather than not-found.","commonSituations":"Dolt/driver connectivity problems, locked or corrupted database, schema drift between planes, or a bug in the wisp use case that returns a non-sentinel error during normal issue lookup flows.","solutions":["Inspect the wrapped cause (errors.Unwrap / %w chain) to identify the underlying storage error","Verify database connectivity and that the Dolt DB is healthy (bd doctor / driver health)","Retry the operation if the failure was transient (connection reset, lock timeout)","Confirm the storage schema matches the expected version; run migrations if behind","If it persists, file an issue with the wrapped error and operation context"],"exampleFix":"// before: treating any wisp error as fatal\nif err != nil { return err }\n// after: only abort on non-not-found errors, matching operationIssue semantics\nif err != nil && !errors.Is(err, publicops.ErrNotFound) && !dberrors.IsNoRows(err) {\n    return fmt.Errorf(\"read wisp %s: %w\", id, err)\n}\n// not-found falls through to the durable GetIssue read","handlingStrategy":"try-catch","validationCode":"// Pre-check database reachability before the operation\nif err := db.PingContext(ctx); err != nil { return fmt.Errorf(\"storage unavailable: %w\", err) }","typeGuard":null,"tryCatchPattern":"if _, _, err := op.OperationIssue(ctx, id); err != nil {\n    var nf *fmt.wrapError\n    if errors.Is(err, publicops.ErrNotFound) { /* fall back */ }\n    else if isTransient(err) { /* retry with backoff */ }\n    else { return fmt.Errorf(\"wisp read failed: %w\", err) }\n}","preventionTips":["Keep wisp and durable planes in sync (regular bd dolt push/pull)","Monitor driver/database health before batch operations","Distinguish sentinel errors (ErrNotFound, IsNoRows) from real failures in your retry logic","Log the full wrapped error chain (using %w / errors.Unwrap) for diagnosis"],"tags":["storage","wisp-read","go","error-wrapping"],"backgroundTag":"wisp-read-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}