Troubleshooting
The TACo SDK validates conditions with Zod, and Zod's error messages are precise but terse. This page maps the errors you will actually see to what they mean and how to fix them.
The fastest workflow: run the validator script, copy the error, look it up here (or paste it into an LLM with the building-with-llms guide).
Schema-shape errors
Invalid literal value, expected "and" (or "or", "not")
You wrote "operator": "AND" or "operator": "&&". Operators are lowercase strings. Allowed: "and", "or", "not".
Invalid literal value, expected "compound" (or any other conditionType)
conditionType is wrong or missing. Each condition type has an exact required string — see the schema reference. Common typos: "contractCondition" (should be "contract"), "jsonApi" (should be "json-api"), "ifThenElse" (should be "if-then-else"), "signingAttribute" (should be "signing-attribute").
Required on a field you thought was optional
The schema reference marks required fields with (*). Common surprises:
ContractCondition.parametersis required (use[]if the function takes none)ContractCondition.contractAddressis requiredJsonApiCondition.endpointis requiredEcdsaCondition.verifyingKeyandcurveare requiredTimeCondition.chainis required (methoddefaults to"blocktime")
Array must contain at least 2 element(s) on a SequentialCondition
SequentialCondition.conditionVariables requires 2–20 entries. If you only need one variable, you do not need a SequentialCondition — just use the inner condition directly.
Array must contain at most 5 element(s) on a CompoundCondition
CompoundCondition.operands is capped at 5. To express more, embed a SequentialCondition (or nest another MultiCondition, within the shared depth limit — see next).
MultiCondition nesting depth exceeded
Nesting is limited to 4 levels, counted across all MultiConditions collectively: CompoundCondition, IfThenElseCondition, and SequentialCondition. A compound → if-then-else → sequential chain is three levels, even though no single type is nested within itself. If you hit the limit, flatten the policy — often a SequentialCondition with early-exit logic replaces several nested compounds.
String must match pattern /^:[a-zA-Z_][a-zA-Z0-9_]*$/
A context variable name is malformed. They must start with :, followed by a letter or underscore, then letters/digits/underscores. No dots, dashes, spaces, or leading digits. See Context Variables.
Invalid url on JsonApiCondition.endpoint
endpoint must be a literal HTTPS URL. You cannot pass a context variable here. If you need a dynamic endpoint, you must commit to a specific service at encryption time.
Invalid hex string on verifyingKey, contractAddress, etc.
Hex strings must contain only 0-9a-fA-F. verifyingKey (Ed25519/SECP256k1 raw bytes) does not include a 0x prefix; addresses do. Check the schema for which is which.
Logical errors that pass validation but fail at runtime
These do not produce a Zod error — they fail when the network actually evaluates the condition. Symptoms: decryption requests are rejected by Porter or by individual nodes.
"Decryption denied" but the condition looks right
Wrong chain ID. A condition that calls Base USDC with
"chain": 1(Ethereum) will hit a contract that does not exist there. Sanity-check every chain ID.Stale block tag.
RpcConditiondefaults its block tag to"latest", but you can pass"finalized"or"safe". If you used"earliest", you are reading genesis state.Comparator inverted.
<vs>=typos are surprisingly common. Re-read the test out loud: "the value must be greater than or equal to X."
"Cannot decode result" from a ContractCondition
The function exists but the outputs array in your functionAbi does not match what the contract actually returns. Double-check against the source contract or a block explorer's verified ABI.
JsonCondition test always fails
Your JSONPath probably does not match. JSONPath is picky:
Filter expressions need parens:
[?(@.name == "amount")], not[@.name == "amount"].Array element access uses
[0], not.0.Test your path against the actual JSON in jsonpath.com before deploying.
SigningObjectAbiAttributeCondition rejects valid calldata
Function signature must be exact, including parameter types —
transfer(address,uint256)nottransfer(address, uint256)(no spaces) and nottransfer(address,uint)(uintis invalid; useuint256).For tuple parameters, use
(type1,type2,...). Example from the Discord tipping bot deep-dive:execute((address,uint256,bytes)).subIndiceswalk into nested structures one level at a time. For a tuple(address, uint256, bytes),subIndices: [2]selects thebytesfield.
SequentialCondition variable not found
You wrote :varname but the bound varName was varName (no leading colon, case-sensitive). The binding uses the bare name; the reference uses : + name.
When all else fails
Run
validate-conditions.tsand read the full error invalidation-error.txt.Compare against the closest example in the cookbook.
Paste the error + your condition + the schema reference URL into an LLM. See Building Conditions with an LLM.
Test end-to-end against a local testnet (see Quickstart) or your own integration.
Last updated