{"record":{"id":"210220f32e1da37b","repo":"XTLS/Xray-core","slug":"invalid-geodata-cron-210220","errorCode":null,"errorMessage":"invalid geodata cron","messagePattern":"invalid geodata cron","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"infra/conf/geodata.go","lineNumber":53,"sourceCode":"\t}\n\tif u.Scheme != \"https\" || u.Host == \"\" {\n\t\treturn errors.New(\"scheme must be https\")\n\t}\n\treturn nil\n}\n\ntype GeodataConfig struct {\n\tCron     *string               `json:\"cron\"`\n\tOutbound string                `json:\"outbound\"`\n\tAssets   []*GeodataAssetConfig `json:\"assets\"`\n}\n\nfunc (c *GeodataConfig) Build() (proto.Message, error) {\n\tconfig := &geodata.Config{}\n\n\tif c.Cron != nil {\n\t\tif _, err := cron.ParseStandard(*c.Cron); err != nil {\n\t\t\treturn nil, errors.New(\"invalid geodata cron\").Base(err)\n\t\t}\n\t\tconfig.Cron = *c.Cron\n\t}\n\n\tconfig.Outbound = c.Outbound\n\n\tassets := make([]*geodata.Asset, 0, len(c.Assets))\n\tfor _, asset := range c.Assets {\n\t\tbuilt, err := asset.Build()\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tassets = append(assets, built)\n\t}\n\tconfig.Assets = assets\n\n\treturn config, nil\n}","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/infra/conf/geodata.go#L35-L71","documentation":"Thrown by GeodataConfig.Build when the optional geodata cron expression fails robfig/cron's ParseStandard. The cron field schedules automatic geodata asset updates; it must be a valid standard 5-field cron expression (with optional @every-style support per ParseStandard). The parse error is attached as the base cause.","triggerScenarios":"Setting the geodata block's cron to a malformed expression such as \"* * *\" (too few fields), \"61 * * * *\" (out-of-range minute), or \"every 1h\" (not a recognized @every duration).","commonSituations":"Copy-paste of 6-field Quartz-style cron from Java tooling; assuming natural-language schedules work; typos in @every durations like \"@every 1 d\".","solutions":["Use a standard 5-field cron expression, e.g. \"0 4 * * *\" for 04:00 daily","Use the @every form with a valid duration, e.g. \"@every 12h\"","Read the chained base error, which names the exact field or token cron rejected"],"exampleFix":"// before\n\"cron\": \"every 1h\"\n// after\n\"cron\": \"@every 1h\"","handlingStrategy":"try-catch","validationCode":"if _, err := cron.ParseStandard(cfg.Cron); err != nil {\n\treturn fmt.Errorf(\"bad cron %q: %w\", cfg.Cron, err)\n}","typeGuard":null,"tryCatchPattern":"// Go: pre-validate cron before config build\nif c.Cron != nil {\n\tif _, err := cron.ParseStandard(*c.Cron); err != nil {\n\t\t// surface early with config context instead of failing inside Build\n\t\treturn fmt.Errorf(\"geodata.cron invalid: %w\", err)\n\t}\n}","preventionTips":["Use standard 5-field cron or @every with a valid duration","Run config through xray run -test (or equivalent) to catch build errors before deploy"],"tags":["xray","config","geodata","cron","scheduling","validation"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}