{"record":{"id":"0c3038ce21f124a2","repo":"gastownhall/beads","slug":"db-dependencysqlrepository-insert-dep-must-not-b","errorCode":null,"errorMessage":"db: DependencySQLRepository.Insert: dep must not be nil","messagePattern":"db: DependencySQLRepository\\.Insert: dep must not be nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/dependency.go","lineNumber":73,"sourceCode":"\t\treturn \"depends_on_external\", nil\n\t}\n\tvar probe int\n\terr := r.runner.QueryRowContext(ctx, \"SELECT 1 FROM wisps WHERE id = ? LIMIT 1\", dependsOnID).Scan(&probe)\n\tswitch {\n\tcase err == nil:\n\t\treturn \"depends_on_wisp_id\", nil\n\tcase errors.Is(err, sql.ErrNoRows):\n\t\treturn \"depends_on_issue_id\", nil\n\tcase dberrors.IsTableNotExist(err):\n\t\treturn \"depends_on_issue_id\", nil\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"classify dep target %s: %w\", dependsOnID, err)\n\t}\n}\n\nfunc (r *dependencySQLRepositoryImpl) Insert(ctx context.Context, dep *types.Dependency, actor string, opts domain.DepInsertOpts) error {\n\tif dep == nil {\n\t\treturn errors.New(\"db: DependencySQLRepository.Insert: dep must not be nil\")\n\t}\n\tif dep.IssueID == \"\" {\n\t\treturn errors.New(\"db: DependencySQLRepository.Insert: IssueID must not be empty\")\n\t}\n\tif dep.DependsOnID == \"\" {\n\t\treturn errors.New(\"db: DependencySQLRepository.Insert: DependsOnID must not be empty\")\n\t}\n\tif dep.IssueID == dep.DependsOnID {\n\t\t// Lead with the sentinel so this defensive repo-layer guard renders like\n\t\t// every other self-dep site (\"cannot add self-dependency: X cannot depend\n\t\t// on itself\") instead of appending the sentinel text.\n\t\treturn fmt.Errorf(\"db: DependencySQLRepository.Insert: %w: %s cannot depend on itself\", domain.ErrSelfDependency, dep.IssueID)\n\t}\n\n\tmetadata := dep.Metadata\n\tif metadata == \"\" {\n\t\tmetadata = \"{}\"\n\t}","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/dependency.go#L55-L91","documentation":"DependencySQLRepository.Insert returns this error when the dep argument is nil. It is the first of several defensive guards in Insert validating the dependency record before any SQL write. A nil dependency carries no IssueID/DependsOnID so it can never be persisted.","triggerScenarios":"Calling Insert(ctx, nil, actor, opts) — usually from a caller that built the *types.Dependency conditionally and skipped initialization on some code path, or passed a nil pointer from a map/slice lookup.","commonSituations":"A lookup that returned nil, nil (not found) and the result was passed to Insert unchecked; optional dependency creation where the dep pointer was left nil.","solutions":["Check dep != nil at the call site before invoking Insert.","Fix the upstream construction path so a valid *types.Dependency is always built.","If the dependency is legitimately absent, skip the Insert rather than calling it."],"exampleFix":"// before\nvar dep *types.Dependency\nrepo.Insert(ctx, dep, actor, opts) // panics-free but errors\n// after\nif dep == nil {\n    return nil // nothing to insert\n}\nrepo.Insert(ctx, dep, actor, opts)","handlingStrategy":"validation","validationCode":"if dep == nil {\n    return fmt.Errorf(\"dependency not initialized\")\n}","typeGuard":"func depValid(d *types.Dependency) bool { return d != nil }","tryCatchPattern":"if err := repo.Insert(ctx, dep, actor, opts); err != nil {\n    if strings.Contains(err.Error(), \"dep must not be nil\") {\n        // skip or construct dependency\n    }\n}","preventionTips":["Never pass lookup results to Insert without a nil check","Construct dependencies via a single validated constructor","Return not-found explicitly instead of nil pointers"],"tags":["validation","dependency","go","storage"],"backgroundTag":"nil-argument","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}