{"record":{"id":"d18bb75736996358","repo":"dbt-labs/dbt-core","slug":"0-9a-za-z","errorCode":null,"errorMessage":"[^0-9a-zA-Z_]+","messagePattern":"\\[\\^0-9a-zA-Z_\\]\\+","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"info","filePath":"crates/dbt-parser/src/resolve/resolve_tests/persist_generic_data_tests.rs","lineNumber":1131,"sourceCode":"\n    let embedded_cfg = match kwargs.get(\"config\") {\n        Some(Value::Object(obj)) => {\n            serde_json::from_value(Value::Object(obj.clone())).map_err(|e| {\n                fs_err!(\n                    ErrorCode::DbtYamlValidationError,\n                    \"Failed to convert embedded config: {}\",\n                    e\n                )\n            })?\n        }\n        _ => dbt_yaml::Value::Mapping(dbt_yaml::Mapping::new(), Span::default()),\n    };\n\n    Ok(merge_yaml_values(passed_in_cfg, embedded_cfg))\n}\n\nstatic CLEAN_REGEX: LazyLock<Regex> =\n    LazyLock::new(|| Regex::new(r\"[^0-9a-zA-Z_]+\").expect(\"valid regex\"));\n\n/// Narrow sanitizer for the test-name segments that become a filename\n/// (`source_name` / `resource_name`). The synthesized name is used directly\n/// as `target/generic_tests/<name>.sql`, so only path separators must be\n/// rewritten — anything else is left alone to avoid changing test names /\n/// `unique_id`s for inputs that already worked (e.g. `prod.events`,\n/// `my-source`).\nstatic PATH_UNSAFE_REGEX: LazyLock<Regex> =\n    LazyLock::new(|| Regex::new(r\"[/\\\\]\").expect(\"valid regex\"));\n\n/// Generates a unique hash for a generic test based on uncleaned kwargs.\n/// This matches mantle's behavior where the unique_id includes a hash of the\n/// test metadata (namespace, name, kwargs) WITHOUT cleaning, ensuring that\n/// tests with different expressions (e.g., '> 0' vs '= 0') get different\n/// unique_ids even if their cleaned names would be identical.\n///\n/// https://github.com/dbt-labs/dbt-core/blob/2ef17b836e39d1b4c7a55f14b448a2254378302e/core/dbt/parser/schema_generic_tests.py#L104-L117\nfn generate_test_unique_id_hash(","sourceCodeStart":1113,"sourceCodeEnd":1149,"githubUrl":"https://github.com/dbt-labs/dbt-core/blob/0267ce9170576975b76b64ce856b2e5848e96617/crates/dbt-parser/src/resolve/resolve_tests/persist_generic_data_tests.rs#L1113-L1149","documentation":"A panic from `Regex::new(r\"[^0-9a-zA-Z_]+\").expect(\"valid regex\")` — a compile-time-constant regex used to sanitize test-name segments (`CLEAN_REGEX`, replacing every character that is not alphanumeric or underscore). Because the pattern is a hardcoded literal that is syntactically valid, this expect can only fire if the regex engine itself fails to compile a known-good pattern (e.g. engine bug, memory exhaustion at first use, or the constant was edited to an invalid pattern).","triggerScenarios":"Practically never from user input — the pattern is static. It can only trigger on first use of `CLEAN_REGEX` if the regex crate fails to compile the literal pattern, e.g. due to a runtime fault, a modified build, or someone editing the constant to an invalid expression.","commonSituations":"A developer edits the constant and introduces a syntax error (e.g. unbalanced `[`), a forked/patched regex crate with broken behavior, or extremely constrained environments where lazy compilation fails.","solutions":["If the constant was modified, restore a valid pattern such as `[^0-9a-zA-Z_]+` (or fix the syntax error)","Run `cargo build`/tests — regex compilation errors in static patterns are usually caught by tests exercising generic-test name sanitization","If it reproduces with the stock pattern, check the regex crate version for regressions and pin/upgrade accordingly"],"exampleFix":"// before (edited, invalid)\nstatic CLEAN_REGEX: LazyLock<Regex> =\n    LazyLock::new(|| Regex::new(r\"[^0-9a-zA-Z_\" ).expect(\"valid regex\"));\n\n// after\nstatic CLEAN_REGEX: LazyLock<Regex> =\n    LazyLock::new(|| Regex::new(r\"[^0-9a-zA-Z_]+\").expect(\"valid regex\"));","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// wrap parser invocation; this panic is not user-recoverable, but catch at a boundary\nlet result = std::panic::catch_unwind(|| run_parse(...));\nif result.is_err() {\n    eprintln!(\"parser panicked compiling internal regex; check regex crate build/version\");\n}","preventionTips":["Do not edit static regex constants without validating the pattern","Add a unit test that touches CLEAN_REGEX so bad edits fail at test time, not at runtime","Pin a known-good regex crate version","Keep panic=abort boundaries and catch_unwind hooks around parse entry points in embedded usage"],"tags":["rust","regex","static-initialization","parser"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"0267ce9170576975b76b64ce856b2e5848e96617","analyzedAt":"2026-09-07T21:53:39.732Z","contentChangedAt":"2026-09-07T21:53:39.732Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}