gastownhall/beads · error
invalid fromRef: %w
Error message
invalid fromRef: %w
What it means
DiffInTx validates both refs with ValidateRef before interpolating them into a dolt_diff() table-function call; this error is raised when fromRef fails validation. The library rejects refs containing SQL metacharacters or invalid forms because dolt_diff requires literal ref names. It is a caller-input error, not a database failure.
Source
Thrown at internal/storage/issueops/diff.go:18
package issueops
import (
"context"
"database/sql"
"fmt"
"github.com/steveyegge/beads/internal/storage"
"github.com/steveyegge/beads/internal/types"
)
// DiffInTx returns changes between two commits or branches by querying
// Dolt's dolt_diff() table function.
//
// nolint:gosec // G201: refs are validated by ValidateRef() - dolt_diff requires literal refs
func DiffInTx(ctx context.Context, tx *sql.Tx, fromRef, toRef string) ([]*storage.DiffEntry, error) {
if err := ValidateRef(fromRef); err != nil {
return nil, fmt.Errorf("invalid fromRef: %w", err)
}
if err := ValidateRef(toRef); err != nil {
return nil, fmt.Errorf("invalid toRef: %w", err)
}
query := fmt.Sprintf(`
SELECT
COALESCE(from_id, '') as from_id,
COALESCE(to_id, '') as to_id,
diff_type,
from_title, to_title,
from_description, to_description,
from_status, to_status,
from_priority, to_priority
FROM dolt_diff('%s', '%s', 'issues')
`, fromRef, toRef)
rows, err := tx.QueryContext(ctx, query)View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped ValidateRef error to see which rule the ref violated
- Use plain branch/tag/commit names without quotes or special characters as fromRef
- Validate user-supplied refs at your CLI boundary before calling DiffInTx
- Pre-check with ValidateRef yourself to fail fast with a clearer message
Example fix
// before
DiffInTx(ctx, tx, "main'; --", "feature")
// after
from := "main" // plain, validated ref
if err := issueops.ValidateRef(from); err != nil {
return fmt.Errorf("bad from ref %q: %w", from, err)
}
DiffInTx(ctx, tx, from, "feature") Defensive patterns
Strategy: validation
Validate before calling
func validRef(ref string) bool {
if ref == "" || len(ref) > 200 {
return false
}
for _, r := range ref {
if !('a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || '0' <= r && r <= '9' ||
r == '-' || r == '_' || r == '.' || r == '/') {
return false
}
}
return true
}
// call ValidateRef(from) yourself before DiffInTx to fail fast Try / catch
if err := DiffInTx(ctx, tx, from, to); err != nil {
if strings.Contains(err.Error(), "invalid fromRef") {
return fmt.Errorf("usage: from must be a plain branch/tag/commit name, got %q", from)
}
return err
} Prevention
- Always pre-validate user-supplied refs with ValidateRef
- Never pass refs containing quotes, semicolons, or whitespace
- Normalize branch names before calling (trim spaces, reject ranges)
- Keep ref input parsing at one boundary in your CLI
When it happens
Trigger: Calling DiffInTx with a fromRef that is empty, contains quotes/semicolons, or otherwise fails ValidateRef (e.g. "main'; DROP TABLE issues--", a ref with illegal characters, or a non-ref string).
Common situations: Passing raw branch names containing shell-style characters; building refs from untrusted CLI input; typos like trailing slashes or spaces; passing a refspec form the validator rejects.
Related errors
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/dd752a4abbce77ee.
Report an issue: GitHub.