{"record":{"id":"6f050c518bca5ef8","repo":"wasmerio/wasmer","slug":"invalid-job-trigger-s-must-be-pre-deployment","errorCode":null,"errorMessage":"Invalid job trigger '{s}'. Must be 'pre-deployment', 'post-deployment', a valid cron expression such as '0 */5 * * *' or a duration such as '15m'.","messagePattern":"Invalid job trigger '(.+?)'\\. Must be 'pre-deployment', 'post-deployment', a valid cron expression such as '0 \\*/5 \\* \\* \\*' or a duration such as '15m'\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/config/src/app/job.rs","lineNumber":192,"sourceCode":"    }\n}\n\nimpl FromStr for JobTrigger {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        if s == \"pre-deployment\" {\n            Ok(Self::PreDeployment)\n        } else if s == \"post-deployment\" {\n            Ok(Self::PostDeployment)\n        } else {\n            match s.parse::<CronExpression>() {\n                Ok(expr) => Ok(Self::Cron(expr)),\n                _ => {\n                    if let Ok(duration) = s.parse::<PrettyDuration>() {\n                        Ok(Self::Duration(duration))\n                    } else {\n                        Err(anyhow!(\n                            \"Invalid job trigger '{s}'. Must be 'pre-deployment', 'post-deployment', \\\n                a valid cron expression such as '0 */5 * * *' or a duration such as '15m'.\",\n                        ))\n                    }\n                }\n            }\n        }\n    }\n}\n\nimpl FromStr for CronExpression {\n    type Err = Box<dyn std::error::Error + Send + Sync>;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        if let Some(predefined_sched) = s.strip_prefix('@') {\n            match predefined_sched {\n                \"hourly\" => Ok(Self {\n                    cron: \"0 * * * *\".parse().unwrap(),","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/wasmerio/wasmer/blob/8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5/lib/config/src/app/job.rs#L174-L210","documentation":"FromStr for the job trigger enum in lib/config/src/app/job.rs accepts only 'pre-deployment', 'post-deployment', a valid cron expression (parsed as CronExpression), or a duration (parsed as PrettyDuration). If the string matches none of these, this error lists all four accepted forms. It is thrown while parsing job trigger config values from app configuration.","triggerScenarios":"Parsing a `[dependencies]`/jobs trigger string like \"every 5 minutes\", \"*/5\", \"0 */5\" (incomplete cron with missing field), \"15mins\", or a misspelled literal like \"pre-deploy\" via JobTrigger::from_str.","commonSituations":"Typo in 'pre-deployment'/'post-deployment'; cron written with too few fields (needs all five: minute hour dom mon dow); duration units not recognized (e.g. '90s' vs expected forms like '15m'); quotes or whitespace included in the config value.","solutions":["Use exactly 'pre-deployment' or 'post-deployment' for the built-in hooks (lowercase, hyphenated).","Write a full 5-field cron expression, e.g. '0 */5 * * *' instead of '*/5'.","Use a recognized duration form such as '15m', '1h', '30s'.","Trim surrounding whitespace/quotes from the value in your config file.","Verify cron syntax with a validator (crontab.guru) before retrying."],"exampleFix":"// before\nlet trigger: JobTrigger = \"every 5 minutes\".parse()?;\n// after\nlet trigger: JobTrigger = \"15m\".parse()?; // or \"0 */5 * * *\"","handlingStrategy":"validation","validationCode":"// validate trigger string before parsing into JobTrigger\nfn validate_trigger(s: &str) -> Result<(), String> {\n    let s = s.trim();\n    if matches!(s, \"pre-deployment\" | \"post-deployment\") { return Ok(()); }\n    let fields = s.split_whitespace().count();\n    if fields == 5 { return Ok(()); } // full cron form\n    if s.chars().all(|c| c.is_ascii_digit())\n        && s.ends_with(|c: char| \"smhd\".contains(c)) { return Ok(()); } // duration form\n    Err(format!(\"invalid trigger '{s}': use pre-deployment, post-deployment, cron '0 */5 * * *', or '15m'\"))\n}","typeGuard":null,"tryCatchPattern":"match \"every 5 minutes\".parse::<JobTrigger>() {\n    Ok(t) => t,\n    Err(e) if e.to_string().contains(\"Invalid job trigger\") => {\n        eprintln!(\"{e}\\nHint: cron needs 5 fields, e.g. '*/5 * * * *'\");\n        std::process::exit(1);\n    }\n    Err(e) => panic!(\"unexpected parse error: {e}\"),\n}","preventionTips":["Use config autocomplete/schema validation in your editor for job triggers","Always write full 5-field cron expressions","Validate cron with crontab.guru before committing config","Trim whitespace and remove quotes around values in YAML/JSON config"],"tags":["rust","config","validation","cron","parse"],"backgroundTag":"invalid-config-value","analyzedSha":"8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5","analyzedAt":"2026-09-01T23:06:31.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}