{"record":{"id":"c61b5885fd199c14","repo":"gastownhall/beads","slug":"failed-to-clear-ephemeral-flag-on-root-s-w","errorCode":null,"errorMessage":"failed to clear ephemeral flag on root %s: %w","messagePattern":"failed to clear ephemeral flag on root (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/mol_squash.go","lineNumber":330,"sourceCode":"\t// Delete ephemeral children within the same transaction\n\tif !keepChildren {\n\t\tfor _, id := range childIDs {\n\t\t\tif err := w.DeleteIssue(ctx, id, actorName); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to delete child %s: %w\", id, err)\n\t\t\t}\n\t\t\tresult.DeletedCount++\n\t\t}\n\t}\n\n\t// Auto-close the root if it's a wisp — squash completes the molecule lifecycle\n\tif root.Ephemeral {\n\t\treason := fmt.Sprintf(\"Squashed: %d steps → digest %s\", len(children), result.DigestID)\n\t\tif err := w.CloseIssue(ctx, root.ID, reason, actorName); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to close wisp root %s: %w\", root.ID, err)\n\t\t}\n\t\t// Clear ephemeral so the closed root stops being re-emitted by every wisp-table export cycle.\n\t\tif err := w.UpdateIssue(ctx, root.ID, map[string]interface{}{\"wisp\": false}, actorName); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to clear ephemeral flag on root %s: %w\", root.ID, err)\n\t\t}\n\t\tresult.WispSquash = true\n\t}\n\n\treturn result, nil\n}\n\nfunc init() {\n\tmolSquashCmd.Flags().Bool(\"dry-run\", false, \"Preview what would be squashed\")\n\tmolSquashCmd.Flags().Bool(\"keep-children\", false, \"Don't delete ephemeral children after squash\")\n\tmolSquashCmd.Flags().String(\"summary\", \"\", \"Agent-provided summary (bypasses auto-generation)\")\n\n\tmolCmd.AddCommand(molSquashCmd)\n}\n","sourceCodeStart":312,"sourceCodeEnd":345,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/mol_squash.go#L312-L345","documentation":"After closing a wisp root, squash clears its ephemeral flag (sets wisp=false) so the closed root stops being re-emitted by wisp-table export cycles. If w.UpdateIssue fails, the error is wrapped as 'failed to clear ephemeral flag on root %s: %w' and the transaction rolls back.","triggerScenarios":"Squashing an ephemeral root when the flag-clearing update fails: storage write error, database lock, schema mismatch on the wisp/ephemeral column, or root deleted concurrently.","commonSituations":"Older database schema lacking the wisp field; export/sync process holding locks; interrupted upgrade leaving partial wisp metadata.","solutions":["Inspect the wrapped cause; run any pending migrations and bd doctor to verify the wisp field exists","Stop competing bd processes/syncs, then retry the squash","If schema mismatch persists, back up and re-migrate the database before squashing"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Ensure schema supports the wisp field before squashing ephemeral roots\nif root.Ephemeral && !schemaHasWispField() {\n    return fmt.Errorf(\"database schema outdated; run migrations\")\n}","typeGuard":"func isWisp(i *types.Issue) bool { return i != nil && i.Ephemeral }","tryCatchPattern":"err := squashMolecule(ctx, s, root, children, keep, summary, actor)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to clear ephemeral flag\") {\n        log.Printf(\"flag clear failed; rerun migrations: %v\", errors.Unwrap(err))\n    }\n    return err\n}","preventionTips":["Run migrations/bd doctor after every bd upgrade","Avoid exporting wisps while a squash transaction is open","Back up the database before schema-affecting operations"],"tags":["go","storage","update","wisp","transaction"],"backgroundTag":"issue-update-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}