{"record":{"id":"c17a6e0a17247849","repo":"multica-ai/multica","slug":"s-must-be-positive-got-s-use-config-set-s","errorCode":null,"errorMessage":"%s must be positive (got %s); use `config set %s \"\"` to clear it","messagePattern":"(.+?) must be positive \\(got (.+?)\\); use `config set (.+?) \"\"` to clear it","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/cmd/multica/cmd_config.go","lineNumber":287,"sourceCode":"\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)\"\n\t}\n\tif d, err := time.ParseDuration(*v); err == nil && d == 0 {\n\t\treturn *v + \" (disabled)\"","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/cmd/multica/cmd_config.go#L269-L305","documentation":"assignPositiveDuration rejects parsed durations <= 0 (e.g. '0s', '-1ms') for every daemon duration knob it serves. Zero is rejected for the same reason as poll_interval: the daemon resolver only substitutes strictly positive values, so a persisted zero would look configured but be ignored; empty string is the sole way to clear.","triggerScenarios":"`multica config set heartbeat_interval 0s`, `... auto_update_check_interval -1h`, or `... codex_handshake_timeout 0ms`.","commonSituations":"Attempting to disable a behavior by zeroing its interval; negative computed durations in automation.","solutions":["Clear the override instead of zeroing: `multica config set <key> \"\"`.","Set a large positive value if the goal is 'rarely'.","For a real disable, check for a dedicated disable_* toggle rather than zeroing the interval."],"exampleFix":"# before\nmultica config set heartbeat_interval 0s\n# after\nmultica config set heartbeat_interval \"\"","handlingStrategy":"validation","validationCode":"# translate 'disable' into a clear, never a zero\nif [ \"$VAL\" = \"0s\" ] || [[ \"$VAL\" == -* ]]; then VAL=\"\"; fi\nmultica config set heartbeat_interval \"$VAL\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["To revert any positive-duration knob to default, set it to an empty string.","Zero-valued durations are silently ignored by the daemon resolver — never persist them."],"tags":["cli","config","duration","validation","go"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}