403 error when I call the management canister

Hello, when I call the management canister on canisters that I create it gives me a 403. It says I am the controller on ic.rocks and it works to send and get icp with the same principal and with the same agent. Is the management-canister blocking the calls?

@diegop if you have the time, I am looking for a sponse for this question: is the dfx-rust agent the only agent with the current-authorization to call the management-canister and install_code onto new canisters? Are other agents being blocked from installing code onto new canisters?

create_canister can only be called via inter-canister calls. Your wallet, not your principal, is likely to be the controller of your canister. If you want to install code for that canister, you need to ask the wallet to forward install_code call for you. Or you can use dfx to add your principal as the controller of the canister, then you can call install_code directly with your principal.


Thank you, so is the install_code method also only able to be called by cross-canister call? What about for the canister_status method?

Only create_canister and raw_rand are inter-canister only, because both methods need cycles to run. The rest of the methods can be called as ingress message, but you need to be the controller of the canister for most management canister calls.

For some reason when I call the management-canister with this dart-agent it gives me back a 403. I am trying to call the management-canister’s canister_status method and it gives me a 403. It also gives me a 403 when I call the install_code method. I am trying to call it on this canister: bayhi-7yaaa-aaaai-qahca-cai and with this principal: kxmyk-xvfce-zx3tv-azim5-pcehj-sfrcg-qjohx-zdh76-4x6ls-6dlf3-hqe as the caller/controller. You can see on ic.rocks that this principal is the controller of the canister. The dart agent works to send icp with the same kxmyk-principal/controller so I know the signing and ed25519 authorization functions are correct. And the dart-agent works to contact any other canister, only the management canister is giving a 403. I also tried to call the management canister with the agent that dfx uses and then it gave me the correct-sponse. I am thinking that maybe there is some kind of Basic-Auth-token that the dfx agent is sending to the management canister but nothing like that is list in the spec. Do you have any clue what it is?

There is nothing special in dfx, it just makes calls to the management canister either directly or via a wallet. You can see the ic-repl script to see how we install and check status via calls.

My guess is that the dart-agent is not sending the calls as the kxmyk-principal. It’s the same issue with agent-js, you cannot send the message as the dfx principal, as it needs to import the pem file from dfx.


You can check it backwards here is the cbor bytes of a call, you can see the cbor map on cbor.me and check that the sender is the kxmyk-principal and the public-key corresponds to the same kxmyk-principal.

this got a 403.

Do you know what this is used for and how?:
at this line:

I forked the rust agent and printed the headers and the bytes and im not seeing anything different between what the dart agent is sending and what the rust agent is sending but the rust agent works and dart agent gets a 403. If someone has an idea of what the dart agent is missing?

Yes it is giving me the same error as if the caller is not the controller but if I backwards check it, the caller is the correct-controller.

Does someone know what this canister is?: Principal ifxlm-aqaaa-multi-pleco-ntrol-lersa-h3ae | ic.rocks

@sat @jplevyak Do you guys know what this is?

are the boundary nodes doing this?

see this thread also: 403 forbidden error when running command "dfx identity --network ic deploy-wallet <canister-identifer>" - #31 by sakoma.icp

The boundary nodes do not check for access permissions. That is done in the replica based on the signature, controllers and permission requirements of the handler.

1 Like

Hmm thanks, what are these permission requirements of the handler and where can I see them? The signature and the controllers are good in the call I checked 1000 times. It works for me to call any other canister including the ledger and it works to send authorized calls to the ledger to send icp so I know the signature is good, it’s just the management canister that is giving me back a 403, do you know why?

1 Like

The cbor you gave doesn’t seem to match what ic management expects. Specifically, I think canister_status expects the argument to be a record { canister_id: principal }. For example:

 didc encode -t '(record {canister_id : principal})' '(record { canister_id = principal "bayhi-7yaaa-aaaai-qahca-cai" })'

But from your cbor binary, you have something like 4449444C026D7B6C01B3C4B1F2040001010A0000000000E003D40101.

1 Like

Thank you for taking the time to check, in those specific bytes it was a different canister (same controller) and i sent a blob type to see if maybe the management canister expected a blob but i was getting the same result when i sent a PrincipalReference. When i tried the bytes that you posted of the didc output then it works! my PrincipalReference encoder wasnt the same as the didc output!! Thank you @PaulLiu , Great-Gratitude!

I see, my PrincipalReference encoder was putting the PrincipalReference type-code into the candid-type-table as its own index and then referencing that index for the record-item-value-type like it is supposed to do for the candid types that are not primitive. When I treat the PrincipalReference type as a primitive type then it works, hmm, what i got from the candid-spec was that any type that is not primitive should go into its own index in the candid-type-table (but i do remember thinking that the PrincipalReference type should be a primitive type because its type definition is only one byte but i dont think it says that anywhere in the candid-spec because the PrincipalReference is not considered a primitive-type).

So in the summary, whats going on is that the didc and it seems the candid-implementation on the ic treats a PrincipalReference as a primitive candid type, but the spec says:
Every nested type is encoded as either a primitive type or an index into a list of *type definitions* . and the PrincipalReference is not considered a primitive type in the spec.

The Principal type is listed as a reference-type which is separate than the primitive types.
Here is a sample of the candid-bytes i was sending which the ic considered invalid:

and here is the candid-bytes which the ic considered valid:

Whoever wants can see the difference here (reference types are not fully supported by this tool but the difference is in the type-table which can be seen): https fxa77-fiaaa-aaaae-aaana-cai . raw . ic0 . app/explain

@nomeata which one does the candid spec (or the authors of the candid-spec) have in the mind for a PrincipalReference-candid-type within a record?

1 Like

That may be wrong, or at least misleading.

The principal type is primitive for the purpose of whether it can be used directly (-24). You only need to put composite types (those with type arguments) in the type table.

I suggested a fix in Spec: Clarify that the type table may only contain composite types by nomeata · Pull Request #284 · dfinity/candid · GitHub.


Cool, I made a pull request on your pull request, Spec: Give the specific meaning of a composite-type by levifeldman · Pull Request #2 · nomeata/candid · GitHub
to showcase:

1 Like