Problem
If I create a Cadence contract that intends to receive an array (e.g. [UInt64], [String]), or a dictionary (e.g. {Int: String}), when I define the arguments in the deployments section in flow.json and try to deploy the contract with "flow project deploy", the flow-cli crashes with the following message:
runtime error: invalid memory address or nil pointer dereference
[] []
map[device:map[arch:amd64 num_cpu:8] os:map[name:linux] runtime:map[go_maxprocs:8 go_numcgocalls:10 go_numroutines:21 name:go version:go1.23.4] trace:map[span_id:fb8a7dcbb06c18f7 trace_id:09f46eebd528f6cf0cc4bd250733c68c]]
goroutine 1 [running]:
runtime/debug.Stack()
/root/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.4.linux-amd64/src/runtime/debug/stack.go:26 +0x5e
github.com/onflow/flow-cli/internal/command.initCrashReporting.func1(0xc0008fcc88, 0xc00004b4a0)
/go/src/github.com/onflow/flow-cli/internal/command/command.go:355 +0x21e
github.com/getsentry/sentry-go.(*Client).processEvent(0xc001802f00, 0xc0008fcc88?, 0xc00004b4a0, {0x3316c20, 0xc000a6c2c0})
/root/go/pkg/mod/github.com/getsentry/sentry-go@v0.31.1/client.go:628 +0x2d1
github.com/getsentry/sentry-go.(*Client).CaptureEvent(...)
/root/go/pkg/mod/github.com/getsentry/sentry-go@v0.31.1/client.go:444
github.com/getsentry/sentry-go.(*Client).RecoverWithContext(0xc001802f00, {0x0, 0x0}, {0x2784ac0?, 0x4a485b0?}, 0x60?, {0x3316c20, 0xc000a6c2c0})
/root/go/pkg/mod/github.com/getsentry/sentry-go@v0.31.1/client.go:495 +0x1d0
github.com/getsentry/sentry-go.(*Client).Recover(0x1?, {0x2784ac0?, 0x4a485b0?}, 0xc001d35008?, {0x3316c20?, 0xc000a6c2c0?})
/root/go/pkg/mod/github.com/getsentry/sentry-go@v0.31.1/client.go:459 +0x77
github.com/getsentry/sentry-go.(*Hub).Recover(0xc000c9e9f0, {0x2784ac0?, 0x4a485b0?})
/root/go/pkg/mod/github.com/getsentry/sentry-go@v0.31.1/hub.go:330 +0xc5
github.com/getsentry/sentry-go.Recover()
/root/go/pkg/mod/github.com/getsentry/sentry-go@v0.31.1/sentry.go:68 +0x32
panic({0x2784ac0?, 0x4a485b0?})
/root/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.23.4.linux-amd64/src/runtime/panic.go:785 +0x132
github.com/onflow/flowkit/v2/transactions.addAccountContractWithArgs(0xc0019ba210, {{0xc0008ce5e8?, 0x1882?}, {0xc000e61980?, 0xe?}}, {0xc001911000, 0x1, 0x28?})
/root/go/pkg/mod/github.com/onflow/flowkit/v2@v2.2.0/transactions/transaction.go:121 +0x34a
github.com/onflow/flowkit/v2/transactions.NewAddAccountContract(...)
/root/go/pkg/mod/github.com/onflow/flowkit/v2@v2.2.0/transactions/transaction.go:82
github.com/onflow/flowkit/v2.(*Flowkit).AddContract(0xc0019b43c0, {0x3337270, 0x4d343e0}, 0xc0019ba210, {{0xc000d2c000, 0x1840, 0x1a40}, {0xc001911000, 0x1, 0x1}, ...}, ...)
/root/go/pkg/mod/github.com/onflow/flowkit/v2@v2.2.0/flowkit.go:305 +0x325
github.com/onflow/flowkit/v2.(*Flowkit).DeployProject(0xc0019b43c0, {0x3337270, 0x4d343e0}, 0xc00196a780)
/root/go/pkg/mod/github.com/onflow/flowkit/v2@v2.2.0/flowkit.go:739 +0x5fc
github.com/onflow/flow-cli/internal/project.deploy({0x0?, 0x0?, 0x0?}, {{0x0, 0x0}, {0x2bc5ba3, 0x4}, {0x0, 0x0}, {0x0, ...}, ...}, ...)
/go/src/github.com/onflow/flow-cli/internal/project/deploy.go:80 +0x195
github.com/onflow/flow-cli/internal/command.Command.AddToParent.func1(0xc001838500?, {0x4d343e0, 0x0, 0x0})
/go/src/github.com/onflow/flow-cli/internal/command/command.go:147 +0x543
github.com/spf13/cobra.(*Command).execute(0x4aaf600, {0xc000052260, 0x0, 0x0})
/root/go/pkg/mod/github.com/spf13/cobra@v1.9.1/command.go:1019 +0xa7b
github.com/spf13/cobra.(*Command).ExecuteC(0xc000a4bb08)
/root/go/pkg/mod/github.com/spf13/cobra@v1.9.1/command.go:1148 +0x40c
github.com/spf13/cobra.(*Command).Execute(...)
/root/go/pkg/mod/github.com/spf13/cobra@v1.9.1/command.go:1071
main.main()
/go/src/github.com/onflow/flow-cli/cmd/flow/main.go:131 +0x1052
Steps to Reproduce
I've created a simple ExampleNFTContract.cdc to establish a base line:
access(all) contract ExampleContract {
access(all) let param1: String
init(par1: String) {
self.param1 = par1
}
}
Simplest contract possible that receives a single String as argument for the contract constructor and sets it to a single internal variable
If I edit flow.json to provide that one String argument such as:
...
deployments": {
"emulator": {
"emulator-account": [
{
"name": "ExampleContract",
"args": [
{
"type": "String",
"value": "SomeExampleString"
}
]
}
]
}
}
And try to deploy it to the flow-cli emulator, it works 100% of the time. The same is valid for all sorts of Int and UInt, Bool, etc. Basic types have no problem in being used as contract constructors.

But, if I change this simple parameter to an array of any type:
access(all) contract ExampleContract {
access(all) let param1: [Int]
init(par1: [Int]) {
self.param1 = par1
}
}
And adjust flow.json accordingly:
...
"deployments": {
"emulator": {
"emulator-account": [
{
"name": "ExampleContract",
"args": [
{
"type": "Array",
"value": [
{
"type": "Int",
"value": "1"
},
{
"type": "Int",
"value": "5"
},
{
"type": "Int",
"value": "7"
}
]
}
]
}
]
}
}
thus using the format defined for JSON-Cadence in https://cadence-lang.org/docs/json-cadence-spec.
But when I try to deploy this simple contract using the same command:

The rest of the error output is indicated in the problem description.
NOTE 1: This behaviour occurs with all types of arrays and dictionaries. I haven't tested composite elements such as structs, resources, ect.
NOTE 2: I've removed the previous contract before attempted a new deployment (using flow accounts remove-contract ExampleContract
NOTE 3: The Test.deployContract module from the Test module does not have this problem, i.e., in a test file, if I do:
let param1: [Int] = [1, 5, 7]
let err: Test.Error? = Test.deployContract(
name: "ExampleContract",
path: "../contracts/ExampleContract.cdc",
arguments: [param1]
)
This one works fine, with arrays and dictionaries (haven't tried with anything more complex). It's just when I try to pass the constructor argument through the deployments section in flow.json.
Context
I'm working in a more complex contract of which I intend to use either a [UInt64], or a {UInt64: String} as a contract constructor argument to set a access(self) parameter. So far I've been using a workaround where I provide a String with a specific format as argument and then parse it to a [UInt64] internally in the constructor, but this solution is not ideal.
This ExampleContract serves to show how fundamental this problem really is.
I'm currently using flow-cli v2.2.8, but I've detected this behaviour for quite some time now.
I'm developing the Cadence project in a Linux Mint (Debian) machine, using VSCode and the Cadence plugin
Problem
If I create a Cadence contract that intends to receive an array (e.g. [UInt64], [String]), or a dictionary (e.g. {Int: String}), when I define the arguments in the deployments section in flow.json and try to deploy the contract with "flow project deploy", the flow-cli crashes with the following message:
Steps to Reproduce
I've created a simple ExampleNFTContract.cdc to establish a base line:
Simplest contract possible that receives a single String as argument for the contract constructor and sets it to a single internal variable
If I edit flow.json to provide that one String argument such as:
And try to deploy it to the flow-cli emulator, it works 100% of the time. The same is valid for all sorts of Int and UInt, Bool, etc. Basic types have no problem in being used as contract constructors.
But, if I change this simple parameter to an array of any type:
And adjust flow.json accordingly:
thus using the format defined for JSON-Cadence in https://cadence-lang.org/docs/json-cadence-spec.
But when I try to deploy this simple contract using the same command:
The rest of the error output is indicated in the problem description.
NOTE 1: This behaviour occurs with all types of arrays and dictionaries. I haven't tested composite elements such as structs, resources, ect.
NOTE 2: I've removed the previous contract before attempted a new deployment (using
flow accounts remove-contract ExampleContractNOTE 3: The
Test.deployContractmodule from the Test module does not have this problem, i.e., in a test file, if I do:This one works fine, with arrays and dictionaries (haven't tried with anything more complex). It's just when I try to pass the constructor argument through the deployments section in flow.json.
Context
I'm working in a more complex contract of which I intend to use either a [UInt64], or a {UInt64: String} as a contract constructor argument to set a
access(self) parameter. So far I've been using a workaround where I provide a String with a specific format as argument and then parse it to a [UInt64] internally in the constructor, but this solution is not ideal.This ExampleContract serves to show how fundamental this problem really is.
I'm currently using flow-cli v2.2.8, but I've detected this behaviour for quite some time now.
I'm developing the Cadence project in a Linux Mint (Debian) machine, using VSCode and the Cadence plugin