How to fix failed to load daemon config: json: cannot unmarshal in Docker

DockerBEGINNERHIGHUpdated Dec 6, 2025· 445 views

This error occurs when Docker cannot parse daemon.json due to incorrect JSON data types, such as using quoted strings for boolean or numeric values. Fix it by ensuring proper JSON syntax with correct data types in your configuration file.

Quick fix

Fixes failed to load daemon config: json: cannot unmarshal

sudo journalctl -u docker.service -n 50 --no-pager
  1. Check the exact error message
  2. Fix boolean values (remove quotes)
  3. Fix numeric values (remove quotes)
  4. Fix proxy configuration structure
docker — error
sudo journalctl -u docker.service -n 50 --no-pager
failed to load daemon config: json: cannot unmarshal

What this error means

When Docker starts, it attempts to load and parse the daemon configuration file (`/etc/docker/daemon.json` on Linux, `C:\ProgramData\docker\config\daemon.json` on Windows). The "json: cannot unmarshal" error specifically indicates a type mismatch problem - Docker is expecting one data type but finding another. The term "unmarshal" comes from Go (the language Docker is written in) and refers to the process of converting JSON text into Go data structures. When the JSON contains a value of the wrong type - for example, a string `"false"` where a boolean `false` is expected - the unmarshaling fails. This is different from a general JSON syntax error (like missing commas or brackets). The JSON itself is valid, but the values don't match what Docker expects for specific configuration options. Common examples include: - Using `"iptables": "false"` instead of `"iptables": false` - Using `"max-concurrent-downloads": "3"` instead of `"max-concurrent-downloads": 3` - Providing an object where Docker expects an array, or vice versa Docker will refuse to start until you fix the configuration, leaving all container operations unavailable.

Typical symptoms

  • Docker daemon fails to start with 'failed to load daemon config: json: cannot unmarshal' error
  • 'systemctl status docker' shows the service in failed state
  • Error message mentions 'cannot unmarshal string into Go value of type bool'
  • Error message mentions 'cannot unmarshal object into Go value of type []string'
  • Docker commands fail with 'Cannot connect to the Docker daemon'
  • Error occurs after editing daemon.json configuration file
  • journalctl shows JSON unmarshaling errors when Docker service starts

Common causes

  1. Boolean values quoted as strings (e.g., "false" instead of false)
  2. Numeric values quoted as strings (e.g., "3" instead of 3)
  3. Array value provided where object is expected, or vice versa
  4. Incorrect proxy configuration structure (missing 'default' object)
  5. Wrong data type for log-opts or storage-opts values
  6. Copy-pasted configuration from documentation with incorrect formatting
  7. Configuration value using outdated format from older Docker version

How to fix "failed to load daemon config: json: cannot unmarshal"

1Check the exact error message

First, get the full error message to identify which configuration key has the wrong type:

On Linux (systemd):

bash
sudo journalctl -u docker.service -n 50 --no-pager

Or check service status:

bash
sudo systemctl status docker.service -l

Look for error patterns like:

- cannot unmarshal string into Go value of type bool - You used "true"/"false" as strings
- cannot unmarshal string into Go value of type int - You quoted a number
- cannot unmarshal object into Go value of type []string - You used an object where an array was expected
- cannot unmarshal array into Go value of type string - You used an array where a single string was expected

The error message will typically include the field name that has the wrong type.

2Fix boolean values (remove quotes)

The most common cause is quoting boolean values. Boolean values in JSON must NOT be quoted.

WRONG - strings instead of booleans:

json
{
  "iptables": "false",
  "debug": "true",
  "live-restore": "true",
  "userland-proxy": "false"
}

CORRECT - actual boolean values:

json
{
  "iptables": false,
  "debug": true,
  "live-restore": true,
  "userland-proxy": false
}

Common boolean options in daemon.json:
- debug
- tls
- tlsverify
- iptables
- ip-forward
- ip-masq
- ipv6
- userland-proxy
- live-restore
- experimental
- selinux-enabled

3Fix numeric values (remove quotes)

Numeric configuration values must also be unquoted.

WRONG - numbers as strings:

json
{
  "max-concurrent-downloads": "3",
  "max-concurrent-uploads": "5",
  "max-download-attempts": "5",
  "shutdown-timeout": "15"
}

CORRECT - actual numbers:

json
{
  "max-concurrent-downloads": 3,
  "max-concurrent-uploads": 5,
  "max-download-attempts": 5,
  "shutdown-timeout": 15
}

Common numeric options:
- max-concurrent-downloads
- max-concurrent-uploads
- max-download-attempts
- shutdown-timeout
- default-shm-size (when specified as bytes, not string like "64M")

4Fix proxy configuration structure

Proxy configuration requires a specific nested structure. The most common mistake is missing the intermediate default key.

WRONG - proxies directly under config:

json
{
  "proxies": {
    "httpProxy": "http://proxy.example.com:3128",
    "httpsProxy": "http://proxy.example.com:3128",
    "noProxy": "localhost,127.0.0.1"
  }
}

CORRECT - proxies nested under default (Docker 23.0+):

json
{
  "proxies": {
    "default": {
      "httpProxy": "http://proxy.example.com:3128",
      "httpsProxy": "http://proxy.example.com:3128",
      "noProxy": "localhost,127.0.0.1"
    }
  }
}

CORRECT - new format (Docker Engine 23.0+):

json
{
  "proxies": {
    "http-proxy": "http://proxy.example.com:3128",
    "https-proxy": "http://proxy.example.com:3128",
    "no-proxy": "localhost,127.0.0.1"
  }
}

Check your Docker version to determine which format to use:

bash
docker --version
5Fix log-opts and storage-opts formatting

Options inside log-opts and storage-opts should generally be strings, but some common mistakes occur:

CORRECT log-opts format (values are strings):

json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3",
    "labels": "production_status",
    "env": "os,customer"
  }
}

WRONG - max-file as number:

json
{
  "log-opts": {
    "max-size": "10m",
    "max-file": 3
  }
}

For log-opts, values should typically be strings since they're passed to the logging driver as key-value pairs.

Storage options are also strings:

json
{
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}

Note that storage-opts is an array of strings, not an object.

6Fix array vs object mismatches

Some configuration options expect arrays, others expect objects. Using the wrong structure causes unmarshal errors.

Options that expect ARRAYS:

json
{
  "dns": ["8.8.8.8", "8.8.4.4"],
  "dns-search": ["example.com"],
  "dns-opts": ["ndots:5"],
  "storage-opts": ["overlay2.override_kernel_check=true"],
  "insecure-registries": ["myregistry.local:5000"],
  "registry-mirrors": ["https://mirror.gcr.io"]
}

Options that expect OBJECTS:

json
{
  "log-opts": {
    "max-size": "10m"
  },
  "runtimes": {
    "nvidia": {
      "path": "/usr/bin/nvidia-container-runtime"
    }
  },
  "default-address-pools": [
    {"base": "172.80.0.0/16", "size": 24}
  ]
}

Note that default-address-pools is an array of objects, each with base and size keys.

7Validate and view current daemon.json

Before restarting Docker, validate your configuration file:

View the current file:

bash
sudo cat /etc/docker/daemon.json

Validate JSON syntax with jq:

bash
sudo cat /etc/docker/daemon.json | jq .

If the JSON is valid, jq will pretty-print it. If invalid, it shows the error.

Check the file location for your setup:

- Standard Linux install: /etc/docker/daemon.json
- Docker in snap (Ubuntu): /var/snap/docker/current/config/daemon.json
- Windows: C:\ProgramData\docker\config\daemon.json
- macOS Docker Desktop: ~/.docker/daemon.json

Create a fresh, minimal config if needed:

bash
sudo tee /etc/docker/daemon.json << 'EOF'
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF
8Restart Docker and verify

After fixing the configuration, restart Docker and verify it's working:

Restart the Docker daemon:

bash
sudo systemctl restart docker

Check the service status:

bash
sudo systemctl status docker

You should see "active (running)" status.

Verify Docker is working:

bash
docker ps
docker info

Verify your configuration was applied:

bash
docker info | grep -A5 "Logging Driver"
docker info | grep "Storage Driver"

The output should reflect your daemon.json settings.

Advanced notes

### Complete daemon.json Type Reference

Here's a reference of correct data types for common daemon.json options:

Boolean options (no quotes around true/false):

json
{
  "debug": true,
  "tls": false,
  "tlsverify": true,
  "iptables": true,
  "ip-forward": true,
  "ip-masq": true,
  "ipv6": false,
  "userland-proxy": true,
  "live-restore": true,
  "experimental": false,
  "selinux-enabled": false,
  "no-new-privileges": false
}

Integer options (no quotes around numbers):

json
{
  "max-concurrent-downloads": 3,
  "max-concurrent-uploads": 5,
  "max-download-attempts": 5,
  "shutdown-timeout": 15,
  "mtu": 1500,
  "default-shm-size": 67108864
}

String options:

json
{
  "storage-driver": "overlay2",
  "log-driver": "json-file",
  "data-root": "/var/lib/docker",
  "exec-root": "/var/run/docker",
  "pidfile": "/var/run/docker.pid",
  "group": "docker",
  "default-runtime": "runc",
  "containerd": "/run/containerd/containerd.sock",
  "cgroup-parent": "",
  "default-cgroupns-mode": "private",
  "seccomp-profile": ""
}

Array of strings options:

json
{
  "dns": ["8.8.8.8", "8.8.4.4"],
  "dns-search": ["example.com"],
  "dns-opts": ["ndots:5"],
  "insecure-registries": ["registry.local:5000"],
  "registry-mirrors": ["https://mirror.example.com"],
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"],
  "labels": ["environment=production", "region=us-east"],
  "storage-opts": ["overlay2.override_kernel_check=true"],
  "default-ulimits": []
}

### Using Docker's Built-in Validator

Docker 18.09+ includes a configuration validator:

bash
dockerd --validate --config-file /etc/docker/daemon.json

This checks the configuration without starting the daemon, helping you catch type errors before restarting.

### Debugging Unmarshaling Errors

If the error message is unclear, you can trace through the configuration:

1. Start with an empty config: {}
2. Add options one at a time
3. Restart Docker after each addition to identify the problematic option

### Version-Specific Differences

Configuration format has changed between Docker versions:

- Docker 17.x and earlier: Some options used different names
- Docker 18.09+: Added --validate flag
- Docker 20.10+: Changed proxy configuration format
- Docker 23.0+: New proxy configuration with http-proxy, https-proxy, no-proxy keys directly under proxies

Check the documentation for your specific Docker version:

bash
docker --version

### Common Pitfalls When Copying from Documentation

When copying configuration from web pages or documentation:

1. Some examples use comments (//) which are not valid in JSON
2. Trailing commas after the last item cause errors
3. Smart quotes (curly quotes) from word processors cause errors
4. Non-breaking spaces or other invisible characters cause issues

Always use a plain text editor and validate with jq before applying.

Frequently asked questions

What does "failed to load daemon config: json: cannot unmarshal" mean?
json on Windows). The "json: cannot unmarshal" error specifically indicates a type mismatch problem - Docker is expecting one data type but finding another. The term "unmarshal" comes from Go (the language Docker is written in) and refers to the process of converting JSON text into Go data structures.
How do I fix "failed to load daemon config: json: cannot unmarshal"?
This error occurs when Docker cannot parse daemon.json due to incorrect JSON data types, such as using quoted strings for boolean or numeric values. Fix it by ensuring proper JSON syntax with correct data types in your configuration file.
What causes "failed to load daemon config: json: cannot unmarshal"?
Boolean values quoted as strings (e.g., "false" instead of false) Numeric values quoted as strings (e.g., "3" instead of 3) Array value provided where object is expected, or vice versa
Is the "failed to load daemon config: json: cannot unmarshal" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading