Error Reference
The two error layers in BlazeRules — strict rule/schema activation versus tolerant per-record ingest — and what each error means.
BlazeRules separates errors into two layers with deliberately different policies. Rule and schema activation is strict — a bad ruleset fails loudly before it can ever run. Per-record ingest is tolerant by default — one malformed record does not abort a batch. Knowing which layer raised an error tells you where to fix it.
Strict where it's cheap, tolerant where it mattersValidating a ruleset happens once, so it is strict. Ingesting records happens millions of times, so the default is to skip and count rather than crash. You can make ingest strict too — see the modes below.
Layer 1 — strict activation
When you call load_rules(...) (or bind a schema), the engine compiles and validates everything before activating it. These problems fail before activation, so a broken ruleset never becomes the active one:
- Bad YAML — the file does not parse.
- Unknown fields — a rule or config key the parser does not recognize.
- Duplicate rule IDs — two rules share an
id. - Invalid regex — a
regex/not_regexpattern RE2 rejects. - Bad lookup files — a missing CSV, wrong columns, or unparseable rows for a referenced
lookup. - Type / operator mismatches — an operator applied to an incompatible field type.
Two ONNX-specific cases fail at the same layer when the library was built with BLAZERULES_ENABLE_ONNX=OFF:
- A
model_scorerule is rejected at compile time. register_model(name, path)throws.
A failed activation does not replace a running rulesetIf activation fails during a hot reload, the previous ruleset stays active. The strictness protects you from swapping in a broken set of rules.
Layer 2 — tolerant ingest
Once rules are active, per-record problems are governed by two EngineConfig modes. The defaults are tolerant; tighten them when you would rather fail than silently drop data.
import blazerules
config = blazerules.EngineConfig()
config.ingest_error_mode = blazerules.IngestErrorMode.SKIP_AND_COUNT # default
config.type_mismatch_mode = blazerules.TypeMismatchMode.NULL_ON_TYPE_ERROR # default| Mode | Values | Default | Behavior |
|---|---|---|---|
ingest_error_mode | SKIP_AND_COUNT | ✓ | Drop the unparseable record, increment messages_skipped and error_counts. |
SKIP_TO_DEAD_LETTER | Route the bad record to a dead-letter log instead of dropping it. | ||
HARD_FAIL | Abort the batch on the first ingest error. | ||
type_mismatch_mode | NULL_ON_TYPE_ERROR | ✓ | Treat a mismatched field value as null for that field. |
COERCE | Attempt a safe type conversion. | ||
HARD_FAIL_TYPE | Abort on the first type mismatch. |
Whatever mode you choose, the per-batch counters on the Result (messages_skipped, error_counts, error_samples) tell you what happened — see Observability.
Python error classes
Activation-layer failures surface as a small hierarchy. Catch the base class to handle any of them, or a specific subclass to react to one cause.
| Class | Base | Raised when |
|---|---|---|
BlazeRulesError | — | Base class for all BlazeRules errors; catch it to handle any of the below. |
BlazeRulesConfigError | BlazeRulesError | Configuration is invalid — unknown fields, conflicting options, an unbuilt feature requested (e.g. register_model with ONNX off). |
BlazeRulesParseError | BlazeRulesError | The rule file fails to parse — malformed YAML or an unparseable SQL expression. |
BlazeRulesSchemaError | BlazeRulesError | Schema is inconsistent — a type/operator mismatch or a field that cannot be bound. |
import blazerules
engine = blazerules.RuleEngine()
try:
engine.load_rules("rules.yaml")
except blazerules.BlazeRulesParseError as e:
print("rule file did not parse:", e)
except blazerules.BlazeRulesSchemaError as e:
print("schema/type problem:", e)
except blazerules.BlazeRulesError as e:
print("activation failed:", e)Symptom → meaning → fix
| Symptom | What it means | Fix |
|---|---|---|
load_rules raises a parse error | Bad YAML, or an unparseable sql: expression | Validate the YAML; check the SQL form against the examples in rules.yaml. |
| "unknown field" / "duplicate id" on load | A typo'd key, or two rules share an id | Correct the key; make every rule id unique. |
| Regex rule rejected at load | RE2 cannot compile the pattern | Fix the regex / not_regex value; RE2 does not accept all PCRE syntax. |
| Lookup error at load | Missing CSV, wrong column, or bad rows | Confirm the path (relative to the rules file) and that the CSV uses the right column (value / value / cidr). |
model_score rejected at compile / register_model throws | Library built with BLAZERULES_ENABLE_ONNX=OFF | Rebuild with ONNX enabled, or remove the model_score rule. See Troubleshooting. |
messages_skipped > 0, records missing | Records failed ingest under SKIP_AND_COUNT | Inspect error_counts / error_samples; switch to SKIP_TO_DEAD_LETTER to capture payloads, or HARD_FAIL to stop. |
| A field is always null in matches | A value did not match the bound type under NULL_ON_TYPE_ERROR | Confirm the field type; use COERCE, or add explicit fields: hints / schema. |
| Batch aborts on a single bad record | ingest_error_mode = HARD_FAIL (or HARD_FAIL_TYPE) | Expected under hard-fail; relax to SKIP_AND_COUNT / SKIP_TO_DEAD_LETTER if one bad record should not stop the batch. |