{"record":{"id":"90b1520e206f1129","repo":"gastownhall/beads","slug":"externaldoltconfig-tlskey-set-without-tlscert","errorCode":null,"errorMessage":"ExternalDoltConfig: TLSKey set without TLSCert","messagePattern":"ExternalDoltConfig: TLSKey set without TLSCert","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/external_dolt_config.go","lineNumber":67,"sourceCode":"\tcase hasHost && !hasPort:\n\t\treturn errors.New(\"ExternalDoltConfig: Host requires Port\")\n\tcase !hasHost && hasPort:\n\t\treturn errors.New(\"ExternalDoltConfig: Port requires Host\")\n\t}\n\n\tif hasHost && (c.Port < 1 || c.Port > 65535) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: Port %d out of range [1, 65535]\", c.Port)\n\t}\n\n\tif hasSocket && !filepath.IsAbs(c.Socket) {\n\t\treturn fmt.Errorf(\"ExternalDoltConfig: Socket %q is not absolute\", c.Socket)\n\t}\n\n\tswitch {\n\tcase c.TLSCert != \"\" && c.TLSKey == \"\":\n\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\")","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/external_dolt_config.go#L49-L85","documentation":"An edge is rejected when its source and target resolve to the same endpoint — i.e. the new issue would depend on itself (or, when Issue.ID matches a referenced ID, the edge collapses onto the new issue). This wraps domain.ErrSelfDependency with the endpoint ID and storage.ErrValidation. Self-dependencies are logically meaningless and would corrupt dependency graphs/cycle detection.","triggerScenarios":"ExecuteCreate/ValidatePublicCreateRequest where a dependency target equals the new issue's ID (endpointFor maps it to the new-issue endpoint), or request.ParentID equals Issue.ID; check at public_create.go:198.","commonSituations":"Auto-generating dependency lists that accidentally include the issue being created; reverse dependencies where the new issue's own ID was used as TargetID; copy-paste of an ID template with the same value in both fields.","solutions":["Remove the dependency entry whose TargetID equals the new issue's ID.","Skip such edges when building dependency lists programmatically.","Check before submitting: reject any dep where TargetID == request.Issue.ID (or ParentID == Issue.ID)."],"exampleFix":"// before\nIssue.ID = \"bd-1\"; req.Dependencies = []publicops.DependencyInput{{TargetID: \"bd-1\", Type: types.DepBlocks}}\n// after\nreq.Dependencies = slices.DeleteFunc(req.Dependencies, func(d publicops.DependencyInput) bool { return d.TargetID == issue.ID })","handlingStrategy":"validation","validationCode":"if req.Issue != nil && req.Issue.ID != \"\" {\n    if req.ParentID == req.Issue.ID { return errors.New(\"self parent\") }\n    for _, d := range req.Dependencies {\n        if d.TargetID == req.Issue.ID { return errors.New(\"self dependency: \" + d.TargetID) }\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := store.ExecuteCreate(ctx, req); err != nil {\n    if errors.Is(err, storage.ErrValidation) && errors.Is(err, domain.ErrSelfDependency) { /* drop the self edge */ }\n    return err\n}","preventionTips":["Filter dependencies whose TargetID equals the new issue's ID.","Watch for Reverse edges that point the new issue at itself.","Guard generated dependency lists against self-references."],"tags":["go","validation","dependencies","self-dependency","graph"],"backgroundTag":"self-dependency","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}