{"record":{"id":"2b40b255753ead60","repo":"hashicorp/nomad","slug":"start-block-for-v-not-a-valid-duration-v","errorCode":null,"errorMessage":"start_block_for %v not a valid duration: %v","messagePattern":"start_block_for (.+?) not a valid duration: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/mock/driver.go","lineNumber":434,"sourceCode":"\t\treturn fmt.Errorf(\"stdout_repeat_duration %v not a valid duration: %v\", c.stdoutRepeatDuration, err)\n\t}\n\n\tif c.stderrRepeatDuration, err = parseDuration(c.StderrRepeatDur); err != nil {\n\t\treturn fmt.Errorf(\"stderr_repeat_duration %v not a valid duration: %v\", c.stderrRepeatDuration, err)\n\t}\n\n\treturn nil\n}\n\nfunc parseDriverConfig(cfg *drivers.TaskConfig) (*TaskConfig, error) {\n\tvar driverConfig TaskConfig\n\tif err := cfg.DecodeDriverConfig(&driverConfig); err != nil {\n\t\treturn nil, err\n\t}\n\n\tvar err error\n\tif driverConfig.startBlockForDuration, err = parseDuration(driverConfig.StartBlockFor); err != nil {\n\t\treturn nil, fmt.Errorf(\"start_block_for %v not a valid duration: %v\", driverConfig.StartBlockFor, err)\n\t}\n\n\tif driverConfig.pluginExitAfterDuration, err = parseDuration(driverConfig.PluginExitAfter); err != nil {\n\t\treturn nil, fmt.Errorf(\"plugin_exit_after %v not a valid duration: %v\", driverConfig.PluginExitAfter, err)\n\t}\n\n\tif err = driverConfig.parseDurations(); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif driverConfig.ExecCommand != nil {\n\t\tif err = driverConfig.ExecCommand.parseDurations(); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n\n\treturn &driverConfig, nil\n}","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/mock/driver.go#L416-L452","documentation":"The mock driver parses the task's StartBlockFor config value into a time.Duration during StartTask via parseDriverConfig. If the string is not a valid Go duration (e.g. \"500\" or \"5x\" instead of \"5s\"), parseDuration fails and the task cannot start, so this wrapped error is returned to the caller.","triggerScenarios":"Calling StartTask with a MockDriverConfig whose StartBlockFor string is not parseable by Go's time.ParseDuration semantics (missing unit suffix, typo, empty string when non-empty is required).","commonSituations":"Typing StartBlockFor = \"1000\" meaning milliseconds instead of \"1s\"; copy-pasting durations from other systems that use \"30m30s\"-free bare numbers; job spec templates that interpolate an empty or malformed value.","solutions":["Fix the StartBlockFor value in the task's driver config to a valid Go duration string (e.g. \"5s\", \"500ms\").","Ensure the value has an explicit unit suffix; bare integers are rejected by time.ParseDuration.","Check the wrapped inner error in the message for the exact parse failure position."],"exampleFix":"// before\nconfig := map[string]interface{}{\"StartBlockFor\": \"500\"}\n// after\nconfig := map[string]interface{}{\"StartBlockFor\": \"500ms\"}","handlingStrategy":"validation","validationCode":"if v, ok := cfg[\"StartBlockFor\"].(string); !ok || v == \"\" {\n    return errors.New(\"StartBlockFor must be a non-empty duration string\")\n} else if _, err := time.ParseDuration(v); err != nil {\n    return fmt.Errorf(\"StartBlockFor %q is not a valid duration: %v\", v, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include a unit suffix in duration config strings (\"5s\", not \"5\").","Run a local time.ParseDuration check in CI over job templates that inject durations."],"tags":["nomad","mock-driver","config","duration-parsing"],"backgroundTag":"invalid-duration-format","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}