Decisions as a Service
Sign Up Now →Sign Up Now

Troubleshooting

Find the symptom, confirm the cause, apply the fix. Every error the runtime raises names what failed; start with the exception type.

Installation#

SymptomCauseFix
pip install helixor-runtime finds no packageThe package is not on the public index yet.Install the wheel from your evaluation access. See Installation.
Import crashes on Python 3.143.14 is not yet supported.Use Python 3.11 or 3.12, the verified versions.
pip install fails with "requires a different Python: … not in '>=3.11'"Changed in 0.3.0: the wheel declares Python 3.11 or later. Earlier wheels declared 3.9 but failed at import on it.Use Python 3.11 or 3.12.
SalesEngineUnavailableError (SALES_ENGINE_NOT_IN_RUNTIME) when you use HelixorSalesEngineChanged in 0.3.1: the sales engine is not part of the runtime. It ran Helixor's own sales playbook, which is not distributed, so in 0.3.0 it always failed with FileNotFoundError.Write your decisions as a playbook, compile it with helixor-pack compile and load it with HelixorEngine.load_pack(). See Add custom rules.
Process aborts on import on macOS with an OpenMP "duplicate library" messageTwo numeric libraries in the environment each load their own OpenMP runtime.Use a clean virtual environment. As a stopgap, set KMP_DUPLICATE_LIB_OK=TRUE.
ModuleNotFoundError: fastapi or websocketsService dependencies missing from a trimmed environment.Reinstall the runtime with its dependencies.

Licenses#

ErrorCauseFix
LicenseSignatureInvalidErrorThe file was edited, truncated, re-encoded, or is not a Helixor license.Use the file exactly as issued. Check line endings if it passed through a secret store.
LicenseExpiredErrorPast valid_until plus the grace period, or the host clock is wrong.Renew, then recompile or re-download packs. Check the host's time sync.
LicenseNotYetValidErrorBefore valid_from, usually a clock running behind.Fix time sync.
LicenseEntitlementErrorThe license does not cover the pack ID or a solver the pack uses.helixor-pack inspect-license and compare its pack patterns with the pack ID.
LicenseNotFoundError; the CLI prints Error: LICENSE_NOT_FOUND: no Helixor license file was found. and exits 1No license in any of the six locations the message lists: the explicit path, HELIXOR_LICENSE_FILE, ./helixor.hxlic, ./helixor.lic, ~/.helixor/helixor.hxlic, ~/.helixor/helixor.lic. Or an explicit path or HELIXOR_LICENSE_FILE names a file that does not exist.Save your license as ~/.helixor/helixor.hxlic with mode 600, pass --license / license_file=, or set HELIXOR_LICENSE_FILE. To get a license, request one on the sign-up page; the CLI cannot mint or sign one.
LicenseLocationAmbiguousError (LICENSE_LOCATION_AMBIGUOUS)One directory holds both helixor.hxlic and the older helixor.lic. The runtime does not guess which to use.Keep one file, preferably helixor.hxlic, or pass the license explicitly.
helixor-pack: error: argument command: invalid choice: 'mint-license'Changed in 0.3.1: the CLI cannot mint or sign licenses.Licenses are issued by Helixor; request one on the sign-up page.

Packs#

ErrorCauseFix
PackUnsealError: content key mismatchThe pack was compiled for a different license, or before a renewal.Recompile or re-download with the license you are running.
PackUnsealError: bad magic, version or integrityTruncated or corrupted file, or not a pack.Re-fetch the artifact and compare its SHA-256 with the one you recorded at build time.
CompilerError: mapping values are not allowed hereAn unquoted value containing : in the playbook.Quote the value. See Playbooks.
FileNotFoundError from HelixorEngine.load_packThe pack does not exist at the path given, or no license was found. A missing license raises LicenseNotFoundError, which is also a FileNotFoundError and lists the locations checked.Fix the path, or put your license where the message says. load_pack never falls back to the built-in pack.
UnsupportedPackDeclarationError at compile or loadThe playbook declares something a compiled pack does not execute: your own codons or hard_rules, a rule type other than regex or luhn_checksum, an action other than block or redact, a rule without id, or an invalid pattern.Read the listed problems; express the logic as supported rules. See Playbooks.
RemovedCapabilityError from compile_custom_ruleChanged in 0.3.0: the method is removed from HelixorEngine, on every engine.Add the rule to the playbook's rules and compile again.
UnsupportedPackDeclarationError at compile, or PackDeclarationUnsealError at load: "actions does not declare …"The playbook lists actions but leaves out an action the pack can return, often the built-in ones.List every action named in the error, or omit actions, and compile again. See Playbook schema.
DecisionBudgetExceededErrorA decision took longer than the pack's budget.max_latency_ms. The result is withheld.Treat it as no decision. Raise the budget if it is tighter than your host can meet.

Evaluation#

SymptomCauseFix
Several triggers, but the action names only one ruleEvery match is reported; the first fatal match decides the action. By design.Explain with action and reason; report everything found from triggers.
CodonRuntimeError from evaluate() on a dictThe dict has no text, message or payload key, or its value is not a string.Pass a string, or put the text under one of those keys. See Evaluating decisions.
AmbiguousPayloadError from evaluate() on a dictThe dict has more than one key, so evaluating one field would leave the others unchecked.Pass the text as a string, or a dict with exactly one of text, message, payload.
LicenseExpiredError from evaluate() on a running compiled packThe license passed its grace period while the process was running.Deploy a renewed license and packs recompiled for it.
A 16-digit number is not treated as a cardIt fails the Luhn check.Expected. Use a real test number such as 4111-1111-1111-1111.
DeveloperQuotaExceededErrorPer-minute or lifetime limit reached on a Developer license whose overage policy is not TRUE_UP. The built-in example pack and compiled packs both enforce the limits.Slow down, or move to a tier without limits.
Wall-clock time is much higher than latency_uslatency_us covers evaluation only. The first call in a process is also slower.Measure end to end; warm the engine at startup with one clean evaluation.

Streaming and services#

SymptomCauseFix
The last words of a stream never arriveflush() was not called.Call session.flush() when the source ends.
StreamBlockedError: Stream blocked by statutory invariantA fatal rule fired inside stream_filter or astream_filter.Expected; catch it and end the response.
ServerConfigurationError: Refusing to bind '0.0.0.0' without authenticationA non-loopback host without a service token.Pass --token or set HELIXOR_SERVICE_TOKEN, or bind 127.0.0.1.
401 Missing or invalid bearer tokenThe service has a token and the request did not send it.Send Authorization: Bearer <token>. GET /v1/health needs no token.
400 "per-request license_key is not accepted"The service serves a compiled pack; a request cannot bring its own license.Drop license_key from the request.
Browser calls fail with a CORS errorCross-origin access is off by default.List the origin in HELIXOR_CORS_ORIGINS. A wildcard is rejected.
WebSocket error with code STREAM_BLOCKEDA stream_chunk after a blocked token. Changed in 0.3.0: the connection stays blocked until the next stream_start.Expected. Close the connection on blocked: true, or send stream_start to begin a new stream.

Known issues and fixes#

Every defect documented for 0.2.1, and its status in runtime 0.3.0. Each status was checked against the released 0.3.0 wheel on 2026-09-29. Builds labelled 0.2.1 were cut from several commits, so when you report an issue against one, give the wheel's SHA-256. Rows marked "Fixed in 0.3.1" were checked against the released 0.3.1 wheel on 2026-10-02; 0.3.1 changes no other row.

Runtime#

IssueAffects 0.2.1Status in 0.3.0
WebSocket stream continues after a blocked token (Services)YesFixed: later chunks get STREAM_BLOCKED until stream_start
A blocked value can stay in a compiled pack's clean_text (Playbook schema)YesFixed: any fired block rule withholds the whole text
A regex rule with capturing groups reports and redacts only the first groupYesFixed: the whole match is reported and redacted
Compiled-pack receipts hash clean_text, so different inputs share a receipt (Receipts)YesFixed: one receipt recipe for both engines, over the input digest
compile_custom_rule() has no public engine it runs on, and does not redact its matchYesFixed: removed, raises RemovedCapabilityError
evaluate(dict) evaluates one text field and ignores the rest (Evaluating decisions)YesFixed: a dict with more than one key raises AmbiguousPayloadError
Compiled packs accept actions, default_action and budget without enforcing themYesFixed: checked at compile and load; budget.max_latency_ms checked on every decision
Compiled packs accept invariants and remedies without executing themYesOpen: still accepted and not executed
Compiled packs do not enforce the license's per-minute and lifetime decision limitsYesFixed
Manifest merkle_root is a placeholder (Pack manifest)YesFixed: it carries the playbook's SHA-256, the same value as raw_pack_sha256
The contact rule's factor names one field (Pack manifest)YesOpen: factor is still has_email; factors lists all three
Package metadata does not match the code: distribution name and versionYesFixed: helixor-runtime 0.3.0. Publishing to the public index is still Planned
The wheel declares Python 3.9 but does not import on itYesFixed: requires Python 3.11 or later, and pip refuses it on 3.9
The wheel does not include the sales playbook, so HelixorSalesEngine() raises FileNotFoundErrorYesOpen in 0.3.0. Fixed in 0.3.1: the sales engine is not part of the runtime, and using it raises SalesEngineUnavailableError (SALES_ENGINE_NOT_IN_RUNTIME)
The customer CLI offers helixor-pack mint-license, and the no-license error tells you to run itYesOpen in 0.3.0. Fixed in 0.3.1: the command is removed; the no-license error points to the sign-up page
The CLI and the Python loaders search different places for the license, and the Python loaders skip the working directoryYesOpen in 0.3.0. Fixed in 0.3.1: one search order for every entry point, canonical name helixor.hxlic
Importing the runtime loads the GPU solver's libraries, about 0.9 s (Benchmarks)YesFixed: import measured at 111 to 129 ms on 0.3.0
Cold start above the 100 ms targetYesOpen in 0.3.0: import alone is 111 to 129 ms. In 0.3.1 at the target, not reliably under it: import, construction and first evaluation took 86.9 to 100.2 ms, measured against the released 0.3.1 wheel on 2026-10-02
HelixorBeliefLedger has no snapshot or restore (Outcome memory)YesFixed: snapshot() and restore()
Generated Python client: caller-supplied action, one cause in the counterfactual (Python)YesFixed: the client bundled with 0.3.0 is regenerated
Generated Python client: NativeRuntimeUnavailableError is not a HelixorRuntimeErrorYesOpen: it derives from RuntimeError only
Generated Java sources: caller-supplied action, isApproved() false for clean payloads, every failure reported as an SSN block, placeholder merkleRoot() (Java)YesFixed in the sources that were in the demo repository's sdks/java; those sources are no longer published (removed from the repository with its 0.3.1 update). They still do not build: the runtime artifact they depend on is Planned

Hosted reasoning service Preview#

IssueAffectsStatus
/v1/decide: p_correct not calibrated, abstentions reported as answers, composed built on abstained questions, require.* and unknown questions ignored (Reasoning service)Service builds before 2026-09-28Fixed on main
Learning loop: a version whose disposition_bands keys are not alphabetical becomes unreadable after a restart (Learning loop)Service builds before 2026-09-28Fixed on main
Learning loop: built-in default golden cases and exception clauseService builds before 2026-09-28Fixed on main: both come from the pack or the request
Playbook turn response does not name the pack version that decidedService builds before 2026-09-28Fixed on main: pack_version, pack_digest, pack_source
Playbook turn takes tenant_id from the request body; outcomes and evolve not scoped to the tenantService builds before 2026-09-28Fixed on main: tenant from your credentials, conflicting tenant refused with 403 tenant_mismatch

Still stuck?#

Email hello@helixor.ai with the runtime version (helixor_runtime.__version__), Python version, the exception type and message, and the output of helixor-pack inspect-license (it shows no key material; remove the contact email line). Never include license files, packs or real payloads.