Json http api: valid jwt returning decoder error

Good afternoon all!

When submitting requests to the json http api, I’m getting

JwtDecoder.Error: 'decode, The token was expected to have 3 parts, but got 1

But the jwt token I’m submitting is not invalid. I’m able to put it in to the debugger at https://jwt.io and it decodes properly and in to the correct data.

This is particularly strange considering the token we are using for the navigator is of the same format, the only difference is no expiry time (for debugging), and the navigator is able to ReadAs and ActAs the party specified in its token. But if I take the navigator token and use it in my application communicating with the json api, I get the same error, the json api is rejecting tokens that the ledger itself is accepting.

Any advice would be greatly appreciated!

1 Like

Hi @lashenhurst, the authorization header you send to the JSON API needs to be prefixed with Bearer (with a space at the end). The token file accepted by Navigator also works without that prefix so I suspect that this might be the difference here.

1 Like

Unfortunately it’s not that simple, we are definitely using "Bearer "

1 Like

That’s odd. Not quite sure what the difference could be. The error comes from the underlying library java-jwt/TokenUtils.java at bf77ffcec4f9ac78e0194f78102b093c8a302707 · auth0/java-jwt · GitHub. This should be used by both the ledger as well as the JSON API (but not by navigator, it doesn’t decode the token) so I’m not quite sure how there should be a mismatch.

1 Like

For clarity, here is the format of the token in question:

  "sub": "testAdminUser",
  "https://daml.com/ledger-api": {
    "ledgerId": "myapp-sandbox",
    "participantId": "sandbox-participant",
    "actAs": [
    "admin": true,
    "readAs": [
  "iss": "my-java-app",
  "exp": 1613671152,
  "authorities": [
1 Like

More things to check:

  • The format is different for websocket requests, because Authorization headers are meaningless in this context.
  • --access-token-file is parsed as well by the same library, so its contents are also relevant.

Thanks Stephen,

We’re not currently using WebSocket for any of our requests, and our --access-token-file for the json api, the navigator, and the initial script were generated by the same java app that is receiving the error, so all follow the format above and have been accepted fine by the ledger.

Would appreciate any other suggestions/advice!

1 Like

Hey @lashenhurst !

  1. Can you share the encoded JWT token that you use in development? Please do not share the production token.
  2. And show how you set it on the client side?

I would like to see the exact encoded token that gets passed to the JSON API. Encoded, not the plain JSON text please.

A valid (encoded) token supposed to have 3 parts: header, payload and a signature, separated by dots (.). It looks to me that for some reason your JWT token gets garbled when passed to the JSON API. Please make sure you copy/pasted the entire thing when configured the client.


This is a good point, and what I would worry about next as well, @lashenhurst.

1 Like

Hi all,

Thanks for your advice, after some poking around underneath the hood it turns out that an errant java class was swapping out the correctly formatted token for an incorrect one at the last second. It wasn’t caught earlier because the class in question is completely unrelated!

It may be worth noting that the JSON API help text does not specify an argument for changing the logging level, something like this may have been able to show the rejected token in the logs, speeding up solution. Might be worthwhile looking in to!

Thanks again!

1 Like

We generally try not to log secrets at any logging level so this wouldn’t help here.

You can actually change the logging level via logback.xml files, see Chapter 3: Configuration for some general documentation on that and How can I make debug statements visible in the sandbox logs? - #2 by cocreature for some of the pitfalls if you try to configure the logback file and run it via assistant. That said, our docs here are sorely lacking and I think a --log-level flag is probably a good idea anyway.

1 Like

+1 +1 +1