{"record":{"id":"5debab27cd06225b","repo":"multica-ai/multica","slug":"s-must-be-a-go-duration-e-g-10s-500ms-w","errorCode":null,"errorMessage":"%s must be a Go duration (e.g. 10s, 500ms): %w","messagePattern":"(.+?) must be a Go duration \\(e\\.g\\. 10s, 500ms\\): %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_config.go","lineNumber":284,"sourceCode":"\t\treturn fmt.Errorf(\"%s must be 'true' or 'false' (got %q)\", key, value)\n\t}\n\t*dst = b\n\treturn nil\n}\n\n// assignPositiveDuration parses value as a strictly-positive Go duration\n// and writes the raw string into dst. Shared by every persisted daemon\n// duration knob except agent_timeout, whose zero value is meaningful.\n// Empty string clears the field.\nfunc assignPositiveDuration(dst *string, key, value string) error {\n\tif value == \"\" {\n\t\t*dst = \"\"\n\t\treturn nil\n\t}\n\tnormalized := strings.TrimSpace(value)\n\td, err := time.ParseDuration(normalized)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%s must be a Go duration (e.g. 10s, 500ms): %w\", key, err)\n\t}\n\tif d <= 0 {\n\t\treturn fmt.Errorf(\"%s must be positive (got %s); use `config set %s \\\"\\\"` to clear it\", key, d, key)\n\t}\n\t*dst = normalized\n\treturn nil\n}\n\n// agentTimeoutDisplay renders the tri-state agent_timeout value for\n// `config show`. nil = not persisted (fall through to env/default);\n// non-nil \"0s\" = explicitly disabled; any other non-nil = the persisted\n// duration string.\nfunc agentTimeoutDisplay(v *string) string {\n\tif v == nil {\n\t\treturn \"(not set)\"\n\t}\n\tif *v == \"\" {\n\t\treturn \"(not set)\"","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_config.go#L266-L302","documentation":"assignPositiveDuration is the shared parser for every persisted daemon duration knob except agent_timeout (heartbeat_interval, codex_semantic_inactivity_timeout, codex_handshake_timeout, auto_update_check_interval). It trims whitespace, parses with time.ParseDuration, and requires Go duration syntax with a unit suffix.","triggerScenarios":"`multica config set heartbeat_interval 30` (no unit), `... 30 sec`, or a value consisting only of whitespace-after-trim artifacts.","commonSituations":"Same bare-number habit as poll_interval; values copied from dash-style configs; compound durations missing a unit on the last component.","solutions":["Write the value with a unit: `multica config set heartbeat_interval 30s`.","To clear: pass an empty string (`config set heartbeat_interval \"\"`)."],"exampleFix":"# before\nmultica config set heartbeat_interval 45\n# after\nmultica config set heartbeat_interval 45s","handlingStrategy":"validation","validationCode":"# unit-suffix check shared by all positive-duration knobs\n[[ \"$VAL\" =~ ^[0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h)+$ ]] || { echo \"bad duration: $VAL\" >&2; exit 2; }\nmultica config set heartbeat_interval \"$VAL\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Every duration knob except agent_timeout needs a unit suffix and a positive value.","Keep a one-line duration regex in wrapper scripts; it catches 90% of config-set failures."],"tags":["cli","config","duration","validation","go"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}