gastownhall/beads · error

count edges in %s: %w

Error message

count edges in %s: %w

What it means

tallyEdgesInTx failed while executing the grouped edge-count query against the plane's dependency table (dependencies or wisp_dependencies). The underlying driver error is wrapped with the table name for diagnosis. Only a missing wisp_dependencies table is tolerated (skipped); every other query error aborts the count.

Source

Thrown at internal/storage/issueops/edge_counts.go:151

// unit-of-work leg. CountDependentRecordsInTx de-duplicates instead, because it
// must agree with a keyset PAGE of the same rows; a cardinality has no page and
// has never de-duplicated.
func tallyEdgesInTx(ctx context.Context, tx DBTX, anchors []string, request publicops.EdgeCountRequest) (map[string]int64, error) {
	tallies := make(map[string]int64, len(anchors))
	for _, plane := range edgeCountPlanes {
		for start := 0; start < len(anchors); start += queryBatchSize {
			end := start + queryBatchSize
			if end > len(anchors) {
				end = len(anchors)
			}
			batch := anchors[start:end]
			query := buildEdgeCountQuery(plane.dependencies, plane.sources, len(batch), request)
			rows, err := tx.QueryContext(ctx, query, edgeCountArgs(batch, request)...)
			if err != nil {
				if optionalBlockedTable(plane.dependencies) && isTableNotExistError(err) {
					break
				}
				return nil, fmt.Errorf("count edges in %s: %w", plane.dependencies, err)
			}
			for rows.Next() {
				var id string
				var n int64
				if scanErr := rows.Scan(&id, &n); scanErr != nil {
					_ = rows.Close()
					return nil, fmt.Errorf("count edges in %s: scan: %w", plane.dependencies, scanErr)
				}
				tallies[id] += n
			}
			_ = rows.Close()
			if err := rows.Err(); err != nil {
				return nil, fmt.Errorf("count edges in %s: rows: %w", plane.dependencies, err)
			}
		}
	}
	return tallies, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error (errors.Unwrap / %w chain) for the root cause and fix accordingly.
  2. Check database connectivity and retry transient failures (connection reset, deadlock) with backoff.
  3. Verify the schema: run migrations so dependencies and wisp_dependencies exist.
  4. Increase the context timeout or investigate why the operation was cancelled.
  5. Check server logs for table corruption or lock contention if errors persist.
Defensive patterns

Strategy: retry

Validate before calling

// Ensure schema before calling:
// SELECT COUNT(*) FROM dependencies — if this fails, run migrations first.

Try / catch

res, err := ExecuteEdgeCount(ctx, tx, req)
if err != nil {
	var retryable bool
	if strings.Contains(err.Error(), "count edges in dependencies:") {
		retryable = isTransient(err) // e.g. driver.ErrBadConn, deadlock, cancelled
	}
	if retryable { res, err = ExecuteEdgeCount(ctx, tx, req) }
}

Prevention

When it happens

Trigger: Calling CountEdges / ExecuteEdgeCount against a Dolt/MySQL backend where the query is invalid, the connection drops mid-query, the context is cancelled, or the dependencies table itself is missing/corrupt; schema migrations removing or renaming dependencies.

Common situations: Database connection timeout or restart during a long batch; a context deadline exceeded because the count was cancelled upstream; running against an old/partial schema missing the dependencies table; locked or corrupt table during migration.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/23e6db0b382ab046. Report an issue: GitHub.