{"record":{"id":"60c37c520582124c","repo":"gastownhall/beads","slug":"ref-cannot-be-empty","errorCode":null,"errorMessage":"ref cannot be empty","messagePattern":"ref cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/migration_content_hashes.go","lineNumber":21,"sourceCode":"import (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/steveyegge/beads/internal/storage/dberrors\"\n)\n\n// validMigrationRefPattern matches the refs this package builds for AS OF reads\n// (Dolt commit hashes or branch/remote-tracking names like\n// \"remotes/origin/main\"). It mirrors issueops.ValidateRef but is kept local so\n// the schema package — which sits below issueops — has no import-cycle risk.\nvar validMigrationRefPattern = regexp.MustCompile(`^[a-zA-Z0-9_./-]+$`)\n\nfunc validateMigrationRef(ref string) error {\n\tif ref == \"\" {\n\t\treturn fmt.Errorf(\"ref cannot be empty\")\n\t}\n\tif len(ref) > 128 {\n\t\treturn fmt.Errorf(\"ref too long\")\n\t}\n\tif !validMigrationRefPattern.MatchString(ref) {\n\t\treturn fmt.Errorf(\"invalid ref format: %s\", ref)\n\t}\n\treturn nil\n}\n\n// ReadMigrationContentHashes reads version -> content_hash from schema_migrations,\n// either at HEAD (ref == \"\") or AS OF ref (e.g. \"remotes/origin/main\"). NULL/empty\n// hashes are dropped. It returns an error when the table, column, or ref is\n// unavailable; the caller classifies it with RemoteRefUnavailableErr /\n// MissingMigrationObjectErr.\n//\n// Dolt requires a literal ref in AS OF: bind parameters (including inside CONCAT)\n// fail server-side with `unbound variable \"v1\" in query`, so the validated ref is","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/migration_content_hashes.go#L3-L39","documentation":"validateMigrationRef rejects an empty ref string. In ReadMigrationContentHashes an empty ref means \"read at HEAD\", so callers hitting this validator via the ref path passed an explicitly empty string where a concrete ref (e.g. \"remotes/origin/main\") was required. The validator mirrors issueops.ValidateRef locally to avoid an import cycle.","triggerScenarios":"Calling ReadMigrationContentHashes with a ref that is non-empty by contract but blank in practice — e.g. an unset config value, an empty branch variable, or a caller that trimmed the ref to \"\" before invoking the ref (AS OF) code path.","commonSituations":"Config file or environment variable for the comparison ref missing/blank; a script interpolating an empty variable into the ref argument; upstream function returning \"\" to signal HEAD while the caller intended a historical read.","solutions":["Supply a concrete ref such as \"remotes/origin/main\" or a branch/tag name.","If HEAD is intended, keep ref == \"\" only at the top-level ReadMigrationContentHashes entry that skips validation, not the AS OF path.","Validate the ref source (config/flag) before calling; fail fast with a clear message.","Default the ref from git remotes when unset."],"exampleFix":"// before\nhashes, err := schema.ReadMigrationContentHashes(ctx, db, cfg.CompareRef) // \"\"\n// after\nref := cfg.CompareRef\nif ref == \"\" {\n    ref = \"remotes/origin/main\"\n}\nhashes, err := schema.ReadMigrationContentHashes(ctx, db, ref)","handlingStrategy":"validation","validationCode":"if ref == \"\" { return errors.New(\"a migration ref is required\") }\n// proceed to ReadMigrationContentHashes(ctx, db, ref)","typeGuard":"func validRef(ref string) bool {\n    return ref != \"\" && len(ref) <= 128 &&\n        regexp.MustCompile(`^[a-zA-Z0-9_./-]+$`).MatchString(ref)\n}","tryCatchPattern":null,"preventionTips":["Never pass empty strings where a ref is expected; use the documented HEAD path instead.","Validate config/env-sourced refs before calling.","Default missing refs to a known-good value like \"remotes/origin/main\"."],"tags":["validation","migration","git-ref"],"backgroundTag":"invalid-git-ref","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}