{"record":{"id":"9d1a5ea5b3f119b6","repo":"JuliusBrussee/caveman","slug":"run-state-listen-address-does-not-match-its-port","errorCode":null,"errorMessage":"run-state listen address does not match its port","messagePattern":"run-state listen address does not match its port","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/internal/runstate/runstate.go","lineNumber":184,"sourceCode":"\treturn os.Rename(tmpName, Path(home, state.Port))\n}\n\nfunc read(home string, port int) (State, error) {\n\traw, err := os.ReadFile(Path(home, port))\n\tif err != nil {\n\t\treturn State{}, err\n\t}\n\tvar state State\n\tif err := json.Unmarshal(raw, &state); err != nil {\n\t\treturn State{}, err\n\t}\n\tif state.Schema != Schema || state.Port != port || state.PID < 1 ||\n\t\tstate.InstanceToken == \"\" || (state.Owner != \"wrap\" && state.Owner != \"start\") {\n\t\treturn State{}, errors.New(\"invalid run-state contract\")\n\t}\n\tlistenPort, err := PortFromListen(state.Listen)\n\tif err != nil || listenPort != state.Port {\n\t\treturn State{}, errors.New(\"run-state listen address does not match its port\")\n\t}\n\treturn state, nil\n}\n\ntype validators struct {\n\talive      func(int) bool\n\texecutable func(int) (string, error)\n\tinstance   func(string, string) bool\n}\n\nfunc validate(state State, checks validators) bool {\n\tif !checks.alive(state.PID) {\n\t\treturn false\n\t}\n\texe, err := checks.executable(state.PID)\n\tif err != nil || !strings.Contains(strings.ToLower(filepath.Base(exe)), \"caveman-proxy\") {\n\t\treturn false\n\t}","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/internal/runstate/runstate.go#L166-L202","documentation":"After the basic contract check, read validates internal consistency: PortFromListen(state.Listen) must succeed and the port embedded in the Listen address must equal state.Port. This error means the Listen field and the Port field disagree or Listen is unparseable, so the state file cannot be trusted for routing or cleanup decisions.","triggerScenarios":"ReadValidated/RemoveMatching encounter a state file where Listen is empty, malformed, or its parsed port differs from the Port field (e.g. Listen '127.0.0.1:8080' but Port 9090).","commonSituations":"Manual edits changing Port but not Listen, corruption of a partially written file, or an old-format state file from a version that stored these independently.","solutions":["Delete the inconsistent state file and restart the proxy to regenerate it","Check that the writer that produces the state file sets Listen and Port from the same source value","Parse the Listen address to confirm it contains a valid :port suffix matching Port"],"exampleFix":"// before (inconsistent file)\n{\"port\":9090,\"listen\":\"127.0.0.1:8080\",...}\n// after (consistent)\n{\"port\":8080,\"listen\":\"127.0.0.1:8080\",...}\n","handlingStrategy":"validation","validationCode":"port, err := runstate.PortFromListen(listen)\nif err != nil || port != wantPort {\n    // regenerate the state file\n}\n","typeGuard":null,"tryCatchPattern":"state, err := runstate.ReadValidated(path, port)\nif errors.Is(err, errors.New(\"run-state listen address does not match its port\")) || err != nil {\n    // delete and rewrite state\n}\n","preventionTips":["Derive Port and Listen from a single source value when writing state","Never edit one field of the state file without the other","Regenerate state after config port changes"],"tags":["runstate","port-mismatch","validation"],"backgroundTag":"invalid-config-value","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}