{"record":{"id":"e651c2bc7245e474","repo":"gastownhall/beads","slug":"count-labels-w","errorCode":null,"errorMessage":"count labels: %w","messagePattern":"count labels: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/delete.go","lineNumber":222,"sourceCode":"\n\tdeletedSet := make(map[string]bool, len(set.All))\n\tfor _, id := range set.All {\n\t\tdeletedSet[id] = true\n\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","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/delete.go#L204-L240","documentation":"DeleteResolvedSetInTx aborts when the SELECT COUNT over the \"labels\" table for the regular issue IDs fails. The message wraps the underlying driver error from CountRowsForIssueIDsInTx. This count feeds the labels-count figure of the dry-run delete result.","triggerScenarios":"Calling DeleteIssuesInTx/DeleteInTx when the labels table is missing or unreadable, the transaction's connection has died, or ctx is cancelled before this point in the count sequence (deps counts succeed, labels count fails).","commonSituations":"Old database schema without the expected labels table layout; Dolt server connection drop mid-transaction; permission loss on the labels table; context timeout set too short for large ID batches.","solutions":["Unwrap the error to see the driver cause (unknown column/table vs connection reset).","Verify schema/migrations have run so labels matches the expected shape.","Retry the operation with a fresh transaction; check for long-held locks on labels.","Increase the context timeout when deleting large issue sets."],"exampleFix":"// before\nctx := context.Background()\nres, err := store.DeleteIssuesInTx(ctx, tx, ids)\n// after\nctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)\ndefer cancel()\nres, err := store.DeleteIssuesInTx(ctx, tx, ids)","handlingStrategy":"retry","validationCode":"if err := db.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"db unreachable before delete: %w\", err)\n}\n// ensure labels table exists\nvar n int\nif err := db.QueryRowContext(ctx, `SELECT COUNT(*) FROM labels LIMIT 1`).Scan(&n); err != nil {\n    return fmt.Errorf(\"labels table unreadable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"res, err := store.DeleteIssuesInTx(ctx, tx, ids)\nif err != nil {\n    var derr driverError\n    if errors.As(err, &derr) && derr.Retryable() {\n        err = retryWithBackoff(3, func() error { _, err = store.DeleteIssuesInTx(ctx, tx, ids); return err })\n    }\n    if err != nil { return err }\n}","preventionTips":["Keep schemas migrated to the beads version you run.","Avoid very short context timeouts on bulk deletes.","Check for lock contention from concurrent writers before large deletes."],"tags":["go","storage","transaction","sql","batch-delete"],"backgroundTag":"sql-count-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}