{"record":{"id":"a68d1dea22348a2f","repo":"gastownhall/beads","slug":"externaldoltconfig-must-set-socket-or-host-port","errorCode":null,"errorMessage":"ExternalDoltConfig: must set Socket or (Host, Port)","messagePattern":"ExternalDoltConfig: must set Socket or \\(Host, Port\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configfile/external_dolt_config.go","lineNumber":48,"sourceCode":"}\n\nfunc (c ExternalDoltConfig) ResolvedUser() string {\n\tif c.User == \"\" {\n\t\treturn ExternalDoltConfigDefaultUser\n\t}\n\treturn c.User\n}\n\nfunc (c ExternalDoltConfig) Validate() error {\n\thasHost := c.Host != \"\"\n\thasPort := c.Port != 0\n\thasSocket := c.Socket != \"\"\n\n\tswitch {\n\tcase hasSocket && (hasHost || hasPort):\n\t\treturn errors.New(\"ExternalDoltConfig: set either Socket OR (Host, Port), not both\")\n\tcase !hasSocket && !hasHost && !hasPort:\n\t\treturn errors.New(\"ExternalDoltConfig: must set Socket or (Host, Port)\")\n\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 != \"\":","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/configfile/external_dolt_config.go#L30-L66","documentation":"A dependency's optional Metadata field, when non-empty, must be valid JSON. validatePublicCreateDependencies runs json.Valid on it and rejects the request with the dependency's index in the message, wrapped as ErrValidation.","triggerScenarios":"ExecuteCreate/ValidatePublicCreateRequest where request.Dependencies[index].Metadata is a non-empty string that fails json.Valid (e.g. bare text, single quotes, trailing comma); check at public_create.go:171.","commonSituations":"Hand-writing metadata strings, templating JSON with unescaped quotes, passing map-like text instead of serialized JSON, or copy-pasting metadata from logs with truncation.","solutions":["Marshal with json.Marshal (or json.Marshal of a map/struct) instead of building the string by hand.","Validate with json.Valid before submitting.","Set Metadata to \"\" if no metadata is needed — empty string is allowed."],"exampleFix":"// before\nMetadata: `{\"key: \"value\"}` // malformed\n// after\nb, _ := json.Marshal(map[string]string{\"key\": \"value\"})\nMetadata: string(b)","handlingStrategy":"validation","validationCode":"for i, d := range req.Dependencies {\n    if d.Metadata != \"\" && !json.Valid([]byte(d.Metadata)) {\n        return fmt.Errorf(\"dependency %d metadata must be valid JSON\", i)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := store.ExecuteCreate(ctx, req); err != nil {\n    if errors.Is(err, storage.ErrValidation) && strings.Contains(err.Error(), \"metadata must be valid JSON\") { /* fix metadata */ }\n    return err\n}","preventionTips":["Always produce Metadata via json.Marshal, never string concatenation.","Run json.Valid on metadata strings before submitting.","Leave Metadata empty when unused."],"tags":["go","validation","json","dependencies","metadata"],"backgroundTag":"invalid-json","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}