{"record":{"id":"05e07917df8eeacb","repo":"shadow1ng/fscan","slug":"webscan-program-create-failed","errorCode":"webscan_program_create_failed","errorMessage":"webscan_program_create_failed: %w","messagePattern":"webscan_program_create_failed: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"webscan/lib/Eval.go","lineNumber":174,"sourceCode":"\n\tvar program cel.Program\n\n\tif cache != nil {\n\t\tif cached, ok := cache[expression]; ok {\n\t\t\tprogram = cached\n\t\t}\n\t}\n\n\tif program == nil {\n\t\tast, issues := env.Compile(expression)\n\t\tif issues.Err() != nil {\n\t\t\treturn nil, fmt.Errorf(\"%s: %w\", i18n.GetText(\"webscan_expression_compile_failed\"), issues.Err())\n\t\t}\n\n\t\tvar err error\n\t\tprogram, err = env.Program(ast, GetBaseProgramOptions()...)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"%s: %w\", i18n.GetText(\"webscan_program_create_failed\"), err)\n\t\t}\n\n\t\tif cache != nil {\n\t\t\tcache[expression] = program\n\t\t}\n\t}\n\n\tresult, _, err := program.Eval(params)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%s: %w\", i18n.GetText(\"webscan_expression_eval_failed\"), err)\n\t}\n\n\treturn result, nil\n}\n\n// URLTypeToString 将 TargetURL 结构体转换为字符串\nfunc URLTypeToString(u *UrlType) string {\n\tvar builder strings.Builder","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/webscan/lib/Eval.go#L156-L192","documentation":"After a successful compile, EvaluateCached builds a runnable program via env.Program(ast, opts...); failure is wrapped as webscan_program_create_failed. This happens when program options (custom functions, optimizations, libraries) conflict with the AST or each other.","triggerScenarios":"Evaluate/EvaluateCached where GetBaseProgramOptions() returns options incompatible with the compiled AST — e.g. a custom function implementation missing, duplicate option registration, or an option failing validation for this expression.","commonSituations":"Registering the same custom function/library twice in options, a custom function declared in the env but not bound in program options, CEL library version upgrade changing option behavior (deprecated APIs).","solutions":["Inspect the wrapped err for which program option failed","Check GetBaseProgramOptions for duplicate/conflicting function bindings","Ensure every function declared in the env has a matching implementation in options","Upgrade/downgrade the cel-go dependency to a compatible version"],"exampleFix":"// before (function declared but not bound)\noptions := []cel.ProgramOption{cel.Functions(...)} // missing cel.CustomTypeProvider etc.\n// after (bind the declared function)\noptions := []cel.ProgramOption{\n    cel.Functions(&cel.FunctionOp{Name: \"contains\", ...}),\n}","handlingStrategy":"try-catch","validationCode":"ast, issues := env.Compile(expr)\nif issues.Err() != nil { return issues.Err() }\n// option conflicts surface at Program(); smoke-test in CI\nif _, err := env.Program(ast, GetBaseProgramOptions()...); err != nil { return err }","typeGuard":null,"tryCatchPattern":"result, err := Evaluate(expr, params)\nif err != nil {\n    if strings.Contains(err.Error(), i18n.GetText(\"webscan_program_create_failed\")) {\n        log.Printf(\"program options mismatch for %q: %v\", expr, err)\n    }\n    return err\n}","preventionTips":["Keep GetBaseProgramOptions free of duplicate function bindings","Smoke-test Evaluate on a trivial expression in CI to catch option regressions","Pin the cel-go version and test upgrades explicitly"],"tags":["go","cel","program","webscan","expression-engine"],"backgroundTag":"internal-invariant-violation","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}