This page addresses problems you are likely to hit while writing Daml code, connecting to APIs, and submitting transactions during local development.Documentation Index
Fetch the complete documentation index at: https://docs.canton.network/llms.txt
Use this file to discover all available pages before exploring further.
Daml Compilation Errors
Common type mismatches
The Daml compiler enforces strict typing. A frequent mistake is passing aContractId where the template type is expected, or vice versa.
fetch to retrieve the contract payload from a ContractId:
Party with Text:
getParty in Daml Script or pass the Party value directly rather than a string.
Missing imports
If the compiler reports an unknown type or function, you likely need an import. Daml does not auto-import modules.SCU compatibility check failures
When upgrading Daml packages, the Smart Contract Upgrade (SCU) compatibility checker may reject changes. Common violations include removing a field from a template or changing a field’s type.API Connection Problems
Wrong port
Each Canton component listens on a different port. If your application getsConnection refused, verify you are targeting the correct one:
- Ledger API (gRPC) — 5001
- JSON API — 7575
- Admin API — 5002
- Participant health — 5003
Auth token issues
If the Ledger API returnsUNAUTHENTICATED, your token may be expired, have the wrong audience, or lack the required scope.
- Token has the
daml_ledger_apiscope - Token audience matches
LEDGER_API_AUTH_AUDIENCEin your config - Token has not expired (check
expclaim)
Sandbox not ready yet
After runningdpm sandbox, the sandbox takes a few seconds to initialize. If your application connects immediately, it may fail with:
Transaction Failures in Development
Authorization errors
The most common transaction rejection is an authorization failure. Canton rejects transactions when the submitting party is not authorized as a signatory or controller.signatory or controller for the relevant choice. If a different party must act, use a delegation pattern where the authorized party creates a contract granting exercise rights.
Contention on the same contract
When two transactions try to exercise a consuming choice on the same contract simultaneously, one will be rejected:- Retry with backoff if the operation is idempotent
- Redesign the workflow to reduce single-contract bottlenecks (e.g., split a counter contract into shards)
- Sequence operations on the client side when ordering matters
Package vetting: DAR not uploaded
If your transaction references a package the validator does not know about, you get:For cn-quickstart, run
make setup then make build before make start. The build step compiles Daml and uploads DARs to the local environment.Additional Daml Error Messages
Error: “<X> is not authorized to commit an update”
This error occurs when there are multiple obligables on a contract. A cornerstone of Daml is that you cannot create a contract that will force some other party (or parties) into an obligation. This error means that a party is trying to do something that would force another parties into an agreement without their consent. To solve this, make sure each party is entering into the contract freely by exercising a choice. A good way of ensuring this is the “initial and accept” pattern: see the Daml patterns for more details.Error: “Argument is not of serializable type”
This error occurs when you’re using a function as a parameter to a template. For example, here is a contract that creates aPayout controller by a receiver’s supervisor:
Hovering over the compilation error displays:
Error: “Recursion limit overflow in module”
The error usually occurs when uploading a DAR to a ledger or using a script via the sandbox. It can manifest on upload as:<- to bind a variable in a do block can incur several layers of recursion in the do block’s serialized representation. Large datatypes with more than 160 fields with deriving clauses can also cause this.
Solving script recursion limits
Normally, one call insidedo introduces 4 layers of recursion, meaning about 250 binds in a script can cause an overflow. However, other expressions in a do block, such as let binds, also introduce a layer of recursion, so functions with fewer binds can also trigger the limit.
Possible workarounds include splitting a large script into multiple scripts or separating logic in the script out into helper functions. For example, assume you have written the following long script:
updateStateOnce, which runs all three choices together.
Note: In many cases, the compiler optimizes your script to produce an expression that does not break the recursion limit despite having many binds. In this example, we have given an intentionally convoluted example that is difficult for the compiler to optimize away.
By using this helper, each block of three exercises is reduced to a single bind, such that myScript now has only 100 binds, well below the recursion limit.
Solving datatype recursion limits
Large datatypes withderiving clauses can also cause overflow errors. Consider the following case of a datatype with 300 fields and a deriving Show instance:
deriving Show clause means that instance of Show MyData is automatically derived to be something like the following:
show has an expression that becomes more and more deeply nested as you go along. Once the number of fields exceeds about 160, this expression has the potential to reach the depth necessary to cause an overflow in its serialized representation in the DAR.
Similarly to Daml Scripts, the recommended workaround for this issue is to split your datatype into many parts. For example, we could create an additional datatype Helper which contains the elements a, b, and c, and use that within MyData:
MyData now has only 100 fields to traverse and nest. Similarly to scripts, it is a good idea to keep your datatypes small, by maximizing code reuse and splitting logic into maintainable chunks.