Troubleshooting
Common issues and solutions for datalogic-rs.
Rust Issues
“Invalid operator: xyz”
Cause: Using an unrecognized operator name.
Solutions:
- Check the operator name spelling (operators are case-sensitive).
- Register a custom operator on the builder.
- Enable templating mode (requires
feature = "templating") — unknown keys then become literal output fields.
// Option 1: Fix spelling
let logic = r#"{"and": [...]}"#; // not "AND"
// Option 2: Custom operator
let engine = datalogic_rs::Engine::builder()
.add_operator("xyz", XyzOperator)
.build();
// Option 3: Templating mode (feature = "templating")
#[cfg(feature = "templating")]
let engine = datalogic_rs::Engine::builder().with_templating(true).build();
A template key runs as an operator instead of being emitted
Cause: This is the inverse of the error above, and it is quieter: you get no error at all, just the wrong result. In templating mode a single-key object is always an operator invocation, so a key that happens to name a built-in runs the operator instead of becoming an output field.
{ "type": { "var": "x" } }
// against {"x": 1} -> "number" (the `type` operator ran)
// expected -> {"type": 1}
Around 60 names are affected: type, map, filter, if, keys,
values, entries, length, in, sort, now, try, cat, +,
== and the rest of the operator table, plus any custom operator you
registered. Note that the same key behaves differently with siblings:
{"type": X, "other": 1} emits both keys, because multi-key object keys
are always literal.
Solution: enable the key escape and prefix the key with it. Exactly one leading prefix is stripped, and an escaped key is never resolved as an operator.
#[cfg(feature = "templating")]
let engine = datalogic_rs::Engine::builder()
.with_templating(true)
.with_template_key_escape('$')
.build();
{ "$type": { "var": "x" } } // -> {"type": 1}
{ "$$type": 1 } // -> {"$type": 1} (doubling escapes the sigil)
The prefix is a char, not a fixed $, so payloads that already use $
keys (MongoDB documents, JSON Schema output) can pick ~ or # instead.
The setting is off by default, requires feature = "templating", and is
inert outside templating mode. See
Structured Objects
for the full rules.
“Variable not found”
Cause: Accessing a path that doesn’t exist in the data.
Solutions:
- Check the variable path spelling
- Use a default value
- Use
missingto check first
{"var": ["user.name", "Anonymous"]}
{"if": [
{"missing": ["user.name"]},
"No name",
{"var": "user.name"}
]}
Unexpected NaN / Thrown errors from arithmetic
Cause: Non-numeric values in arithmetic operations.
Solution: Configure NaN handling:
use datalogic_rs::{Engine, EvaluationConfig, NanHandling};
let config = EvaluationConfig::default()
.with_arithmetic_nan_handling(NanHandling::IgnoreValue); // or CoerceToZero
let engine = Engine::builder().with_config(config).build();
“the trait bound T: CustomOperator is not satisfied” / Send-Sync errors
Cause: Custom operator type that isn’t Send + Sync.
Solution: Use thread-safe primitives. Avoid Rc, RefCell, etc., in
operator state — wrap shared state in Arc<Mutex<_>> or atomics.
v4 method calls fail to compile in v5
Cause: v5 renamed the public surface (DataLogic → Engine,
CompiledLogic → Logic, Operator → CustomOperator,
evaluate_* → eval_*, etc.) and removed the pre-release compat
shim. v5 is a hard cliff — there is no transitional feature flag.
Solutions:
- Follow the conceptual overview in the Migration Guide
and the per-call cookbook in the repo-root
MIGRATION.md. - Common mappings:
DataLogic::with_config(c)→Engine::builder().with_config(c).build()engine.evaluate_json(rule, data)→engine.eval_str(rule, data)(ordatalogic_rs::eval_str(rule, data)for the zero-config path)engine.evaluate_owned(&compiled, data)→let v: serde_json::Value = engine.session().eval_into(&compiled, &data)?(requiresfeature = "serde_json";Engine::eval_intotakes a rule source, not a compiled&Logic)engine.evaluate_json_with_trace(rule, data)→engine.trace().eval_str(rule, data)returningTracedRun<String>
Slow compilation
Cause: Very large or deeply nested expressions.
Solutions:
- Compile once, evaluate many times
- Break expressions into smaller composable pieces
- Use
feature = "trace"to see which sub-expressions run and how often (the step log carries iteration counts, not timings); for timing, use a sampling profiler such as perf or Instruments (see Performance)
let compiled = engine.compile(rule).unwrap();
let mut session = engine.session();
for data in dataset {
session.eval_str(&compiled, data)?;
session.reset();
}
JavaScript / WASM Issues
“RuntimeError: memory access out of bounds”
Cause: WASM module not initialized.
Solution: Call init() before using any functions:
import init, { evaluate } from '@goplasmatic/datalogic-wasm';
await init();
evaluate(logic, data, false);
“TypeError: Cannot read properties of undefined”
Cause: Wrong import style for your environment.
Solutions:
// Browser/Bundler — need default import for init
import init, { evaluate } from '@goplasmatic/datalogic-wasm';
// Node.js — no init needed
const { evaluate } = require('@goplasmatic/datalogic-wasm');
“Failed to fetch” in browser
Cause: WASM file not accessible from the browser.
Solutions:
- Check your bundler configuration
- Ensure WASM files are served correctly
- Check CORS headers if loading from CDN
For Webpack:
// webpack.config.js
module.exports = {
experiments: {
asyncWebAssembly: true,
},
};
Results are strings, not values
Cause: WASM returns JSON strings, not native values.
Solution: Parse the result:
const resultString = evaluate(logic, data, false);
const result = JSON.parse(resultString);
Performance issues
Cause: Recompiling rules repeatedly.
Solution: Use CompiledRule:
const rule = new CompiledRule(logic, false);
for (const item of items) {
rule.evaluate(JSON.stringify(item));
}
React UI Issues
“ResizeObserver loop completed with undelivered notifications”
Cause: Container size changes rapidly. Usually harmless.
Editor shows blank / empty
Causes:
- Container has no dimensions
- CSS not imported
- Expression is null
Solutions:
<div style={{ width: '100%', height: '500px' }}>
<DataLogicEditor value={expression} />
</div>
import '@goplasmatic/datalogic-ui/styles.css';
Debugger controls not showing
Cause: data prop not provided.
Solution:
<DataLogicEditor
value={expression}
data={{ x: 1, y: 2 }}
/>
With data the toolbar gains the debugger controls (play/pause, step, and a
step timeline). Values appear as you step: the current node shows its context
and result in a bubble. Nodes do not display results at rest.
SSR / Hydration errors in Next.js
Cause: WASM doesn’t run on server.
Solution: Use a client component with dynamic import:
'use client';
import dynamic from 'next/dynamic';
const DataLogicEditor = dynamic(
() => import('@goplasmatic/datalogic-ui').then(mod => mod.DataLogicEditor),
{ ssr: false }
);
Build Issues
WASM build fails
Cause: Missing wasm-pack or target.
Solution:
cargo install wasm-pack
rustup target add wasm32-unknown-unknown
cd bindings/wasm && ./build.sh
TypeScript errors with imports
{
"compilerOptions": {
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
}
}
Bundler can’t find WASM file
// Webpack — enable async WASM
experiments: { asyncWebAssembly: true }
Getting Help
If you can’t resolve an issue:
- Check existing issues
- Create a minimal reproduction
- Open a new issue with:
- datalogic-rs version
- Environment (Rust / Node / Browser)
- Minimal code to reproduce
- Expected vs actual behavior