{"record":{"id":"fab0791dfc5b58ac","repo":"hashicorp/nomad","slug":"plugin-exit-after-v-not-a-valid-duration-v","errorCode":null,"errorMessage":"plugin_exit_after %v not a valid duration: %v","messagePattern":"plugin_exit_after (.+?) not a valid duration: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/mock/driver.go","lineNumber":438,"sourceCode":"\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}\n\nfunc (d *Driver) StartTask(cfg *drivers.TaskConfig) (*drivers.TaskHandle, *drivers.DriverNetwork, error) {\n\tdriverConfig, err := parseDriverConfig(cfg)\n\tif err != nil {","sourceCodeStart":420,"sourceCodeEnd":456,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/mock/driver.go#L420-L456","documentation":"Same duration-parsing failure as start_block_for but for the PluginExitAfter config field: parseDriverConfig validates it during StartTask and rejects the whole task start if the string cannot be parsed as a Go duration.","triggerScenarios":"Calling StartTask with a MockDriverConfig whose PluginExitAfter is not a valid Go duration string (e.g. \"60\" without a unit, or a non-numeric garbage value).","commonSituations":"Setting PluginExitAfter = \"1m\" vs \"60\" confusion; leaving the field as an empty string when a value was expected; environment-variable-substituted config yielding an unparseable value.","solutions":["Correct PluginExitAfter in the task driver config to a valid duration (e.g. \"30s\").","Add an explicit unit suffix to any bare number.","If the inner parse error points to a stray character, remove it and re-run the task."],"exampleFix":"// before\ncfg := map[string]interface{}{\"PluginExitAfter\": \"120\"}\n// after\ncfg := map[string]interface{}{\"PluginExitAfter\": \"2m\"}","handlingStrategy":"validation","validationCode":"if v, ok := cfg[\"PluginExitAfter\"].(string); !ok || v == \"\" {\n    return errors.New(\"PluginExitAfter must be a non-empty duration string\")\n} else if _, err := time.ParseDuration(v); err != nil {\n    return fmt.Errorf(\"PluginExitAfter %q is not a valid duration: %v\", v, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate PluginExitAfter with time.ParseDuration before submitting the job.","Avoid substituting bare numbers from environment variables; format them with an explicit unit."],"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"}