{"record":{"id":"1b6bb4495033541a","repo":"gastownhall/beads","slug":"count-wisp-labels-w","errorCode":null,"errorMessage":"count wisp labels: %w","messagePattern":"count wisp labels: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/delete.go","lineNumber":226,"sourceCode":"\t}\n\n\tvar depsCount, labelsCount, eventsCount int\n\tvar err error\n\tif depsCount, err = CountRowsForIssueIDsInTx(ctx, tx, \"dependencies\", set.RegularIDs); err != nil {\n\t\treturn nil, fmt.Errorf(\"count dependencies: %w\", err)\n\t}\n\twispDepsCount, err := CountRowsForIssueIDsInTx(ctx, tx, \"wisp_dependencies\", set.WispIDs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"count wisp dependencies: %w\", err)\n\t}\n\tdepsCount += wispDepsCount\n\n\tif labelsCount, err = CountRowsForIssueIDsInTx(ctx, tx, \"labels\", set.RegularIDs); err != nil {\n\t\treturn nil, fmt.Errorf(\"count labels: %w\", err)\n\t}\n\twispLabelsCount, err := CountRowsForIssueIDsInTx(ctx, tx, \"wisp_labels\", set.WispIDs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"count wisp labels: %w\", err)\n\t}\n\tlabelsCount += wispLabelsCount\n\n\tif eventsCount, err = CountRowsForIssueIDsInTx(ctx, tx, \"events\", set.RegularIDs); err != nil {\n\t\treturn nil, fmt.Errorf(\"count events: %w\", err)\n\t}\n\twispEventsCount, err := CountRowsForIssueIDsInTx(ctx, tx, \"wisp_events\", set.WispIDs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"count wisp events: %w\", err)\n\t}\n\teventsCount += wispEventsCount\n\n\tfor i := 0; i < len(set.All); i += deleteBatchSize {\n\t\tend := i + deleteBatchSize\n\t\tif end > len(set.All) {\n\t\t\tend = len(set.All)\n\t\t}\n\t\tbatch := set.All[i:end]","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/delete.go#L208-L244","documentation":"DeleteResolvedSetInTx aborts when it cannot count rows in the \"wisp_labels\" table for the wisp IDs in the resolved set. This wraps the driver-level error returned by CountRowsForIssueIDsInTx. The count contributes to the labels figure of the delete result.","triggerScenarios":"Calling DeleteInTx/DeleteIssuesInTx where wisp_labels is absent (pre-wisp schema or driver that doesn't create wisp tables), corrupted, or the connection fails between the labels count and this query.","commonSituations":"Embedded-mode or older storage backend lacking wisp_labels; Dolt schema drift after a version upgrade; transient I/O error on the database file/server.","solutions":["Read the wrapped driver error to distinguish missing table from connection failure.","Run schema migrations / ensure the backend supports wisp tables.","Retry on a fresh transaction if the cause is transient.","Check database server logs around the failure time."],"exampleFix":"// before\nif err != nil {\n    return err\n}\n// after\nif err != nil {\n    var missing tableMissingError\n    if errors.As(err, &missing) {\n        return fmt.Errorf(\"run 'bd migrate' first: %w\", err)\n    }\n    return err\n}","handlingStrategy":"validation","validationCode":"// confirm wisp support before calling delete on wisps\nrows, err := db.QueryContext(ctx,\n    `SELECT table_name FROM information_schema.tables WHERE table_name = 'wisp_labels'`)\nif err != nil || !rows.Next() {\n    return errors.New(\"wisp_labels missing: migrate schema or use a wisp-capable backend\")\n}","typeGuard":null,"tryCatchPattern":"res, err := store.DeleteInTx(ctx, tx, ids)\nif err != nil && strings.Contains(err.Error(), \"wisp_labels\") {\n    return fmt.Errorf(\"backend lacks wisp support or schema is stale: %w\", err)\n}","preventionTips":["Verify the storage backend supports wisp tables (see storage boundary docs).","Run migrations after every beads version upgrade.","Probe information_schema for wisp tables once at startup."],"tags":["go","storage","transaction","sql","wisps"],"backgroundTag":"sql-count-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}