{"record":{"id":"a1d6a7f17daa0620","repo":"gastownhall/beads","slug":"externaldoltconfig-tlscacert-set-without-tlsrequi","errorCode":null,"errorMessage":"ExternalDoltConfig: TLSCACert set without TLSRequired","messagePattern":"ExternalDoltConfig: TLSCACert set without TLSRequired","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/external_dolt_config.go","lineNumber":83,"sourceCode":"\t\treturn errors.New(\"ExternalDoltConfig: TLSCert set without TLSKey\")\n\tcase c.TLSCert == \"\" && c.TLSKey != \"\":\n\t\treturn errors.New(\"ExternalDoltConfig: TLSKey set without TLSCert\")\n\t}\n\n\tif c.TLSCert != \"\" && !filepath.IsAbs(c.TLSCert) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSCert %q is not absolute\", c.TLSCert)\n\t}\n\tif c.TLSKey != \"\" && !filepath.IsAbs(c.TLSKey) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSKey %q is not absolute\", c.TLSKey)\n\t}\n\tif c.TLSCACert != \"\" && !filepath.IsAbs(c.TLSCACert) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: TLSCACert %q is not absolute\", c.TLSCACert)\n\t}\n\n\tif !c.TLSRequired {\n\t\tswitch {\n\t\tcase c.TLSCACert != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSCACert set without TLSRequired\")\n\t\tcase c.TLSCert != \"\" || c.TLSKey != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSCert/TLSKey set without TLSRequired\")\n\t\tcase c.TLSServerName != \"\":\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSServerName set without TLSRequired\")\n\t\tcase c.TLSSkipVerify:\n\t\t\treturn errors.New(\"ExternalDoltConfig: TLSSkipVerify set without TLSRequired\")\n\t\t}\n\t}\n\n\tif c.TLSRequired && hasSocket && c.TLSServerName == \"\" && !c.TLSSkipVerify {\n\t\treturn errors.New(\"ExternalDoltConfig: TLSRequired over Socket needs TLSServerName or TLSSkipVerify\")\n\t}\n\n\tif c.KeepAlivePeriod < 0 {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: KeepAlivePeriod %s is negative\", c.KeepAlivePeriod)\n\t}\n\n\treturn nil","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/external_dolt_config.go#L65-L101","documentation":"The same source->target edge may not appear twice with the same dependency type. validatePublicCreateDependencies deduplicates edges (including the implicit parent edge and waits-for edge) and refuses exact duplicates with this message naming both endpoint IDs, wrapped as ErrValidation. (Same pair with a different type produces a DependencyTypeConflictError instead.)","triggerScenarios":"ExecuteCreate/ValidatePublicCreateRequest where two Dependencies entries produce an identical (source,target,type) edge — e.g. the same TargetID+Type listed twice, or a dependency duplicating the implicit ParentID edge; check at public_create.go:203.","commonSituations":"Merging dependency lists from two sources without deduplication; retry logic re-appending dependencies; Reverse flag and normal direction accidentally producing the same pair; batch templates that already embed the parent edge.","solutions":["Deduplicate request.Dependencies by (TargetID, Type) before submitting.","Remove the entry duplicating the implicit ParentID edge.","Use a set keyed by source:target:type when building dependencies programmatically."],"exampleFix":"// before\nreq.Dependencies = []publicops.DependencyInput{{TargetID: \"bd-2\", Type: types.DepBlocks}, {TargetID: \"bd-2\", Type: types.DepBlocks}}\n// after\nreq.Dependencies = dedupeDeps(req.Dependencies) // keep one {bd-2, blocks} entry","handlingStrategy":"validation","validationCode":"seen := map[string]bool{}\nfor _, d := range req.Dependencies {\n    k := d.TargetID + \":\" + string(d.Type)\n    if seen[k] { return fmt.Errorf(\"duplicate dependency %s\", d.TargetID) }\n    seen[k] = true\n}","typeGuard":null,"tryCatchPattern":"if err := store.ExecuteCreate(ctx, req); err != nil {\n    if errors.Is(err, storage.ErrValidation) && strings.Contains(err.Error(), \"duplicate dependency\") { /* dedupe and retry submit */ }\n    return err\n}","preventionTips":["Deduplicate by (TargetID, Type) before building the request.","Remember the implicit ParentID edge counts toward duplicates.","Use a set when aggregating dependencies from multiple sources."],"tags":["go","validation","dependencies","duplicates"],"backgroundTag":"duplicate-dependency","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}