{"record":{"id":"c50c70a2102bd205","repo":"gastownhall/beads","slug":"db-dependencysqlrepository-insert-record-depende","errorCode":null,"errorMessage":"db: DependencySQLRepository.Insert: record dependency_added event: %w","messagePattern":"db: DependencySQLRepository\\.Insert: record dependency_added event: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/dependency.go","lineNumber":185,"sourceCode":"\t// Record the dependency_added event on the source's event table, matching the\n\t// embedded/issueops AddDependencyInTx path so the bd CLI and library callers\n\t// observe the same history from either write plumbing. Reached only on the\n\t// genuine new-edge path; the idempotent same-type refresh returned earlier.\n\t// Gated on EmitEvent so only the explicit dep verbs emit: create-with-deps\n\t// and reparent call Insert directly without it, so an implicit parent-child /\n\t// --deps / waits-for edge produces no event. The embedded structural paths\n\t// (createIssueWithDeps, reparent) match this by calling the plain,\n\t// no-event AddDependency/tx.AddDependency, whose issueops.AddDependencyInTx\n\t// EmitEvent gate is likewise unset — so both backends stay silent on implicit\n\t// edges and emit only for the explicit bd dep add / bd link verbs.\n\tif opts.EmitEvent {\n\t\tif err := r.events.Record(ctx, domain.Event{\n\t\t\tIssueID:  dep.IssueID,\n\t\t\tType:     types.EventDependencyAdded,\n\t\t\tActor:    actor,\n\t\t\tNewValue: fmt.Sprintf(\"Added dependency: %s %s %s\", dep.IssueID, dep.Type, dep.DependsOnID),\n\t\t}, domain.RecordEventOpts{UseWispsTable: opts.UseWispsTable}); err != nil {\n\t\t\treturn fmt.Errorf(\"db: DependencySQLRepository.Insert: record dependency_added event: %w\", err)\n\t\t}\n\t}\n\n\t// is_blocked maintenance mirrors the classic AddDependencyInTx flow\n\t// (issueops/dependencies.go): the affected set expands the source by its\n\t// parent-child descendants (plus, for parent-child edges, waiters on the\n\t// target spawner), then a Mark pass propagates blocked state — or, for\n\t// parent-child adds (not monotonic: an already-closed child can satisfy an\n\t// any-children waits-for gate), a full mark/unmark Recompute. Skipping the\n\t// expansion left descendants stale when a blocking edge landed on their\n\t// ancestor (bd-6dnrw.44 item 3).\n\tsrcIsWisp := opts.UseWispsTable\n\tvar affectedIssues, affectedWisps []string\n\tvar aerr error\n\tif srcIsWisp {\n\t\taffectedIssues, affectedWisps, aerr = issueops.AffectedByDepChangeForWispInTx(ctx, r.runner, dep.IssueID, dep.DependsOnID, dep.Type)\n\t} else {\n\t\taffectedIssues, affectedWisps, aerr = issueops.AffectedByDepChangeInTx(ctx, r.runner, dep.IssueID, dep.DependsOnID, dep.Type)","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/dependency.go#L167-L203","documentation":"This error wraps a failure from the events repository while recording the dependency_added event after a successful edge insert. The dependency was created, but writing its history entry to the source issue's event table failed, so the emit path aborts with this wrap.","triggerScenarios":"Calling Insert with opts.EmitEvent=true where events.Record fails — event table missing, connection failure, or constraint error writing the Event row for dep.IssueID.","commonSituations":"Older database lacking the events table or expected columns; read-only replica receiving the write; DB connection dropped between dep insert and event record.","solutions":["Check that the events table exists and matches the current schema (bd migrate).","Verify write connectivity; retry the operation.","If the event is non-essential for your flow, call Insert with EmitEvent=false to skip event recording.","Inspect the wrapped driver error for the underlying cause."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := repo.Insert(ctx, dep, actor, opts); err != nil {\n    if strings.Contains(err.Error(), \"record dependency_added event\") {\n        // edge may exist; check before retrying; consider EmitEvent=false if audit not needed\n    }\n}","preventionTips":["Keep the events table migrated to current schema.","Set EmitEvent=false for structural/implicit edges that do not need history.","Write to a primary, not a read-only replica."],"tags":["database","events","audit-log"],"backgroundTag":"event-record-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}