Cog-Creators / Cog-Creators/Red-DiscordBot

Non-dict default with a dict value breaks `Group.all`

Open
#6,648 0 comments 0 reactions 0 assignees View on GitHub
Category: Core - API - Config Status: Needs Discussion Type: Bug
Dominant language
Python
Stars
5.7k
Forks
2.5k
Avg merge
6d 16h
Merged PRs (30d)
1

Description

### What Red version are you using?

3.5.20

### What were you trying to do?

If a config key defaults to a non-dict value (ie, that key is not a Group), storing a dict to that key causes `scope.all()` to error when trying to recursively fetch the default values for that dict's keys. I am only able to reproduce this issue for `.all`, directly accessing the key does not produce an error.

It is unclear whether this should be considered a user error (mixing Groups and Values) and should be entirely prevented or if this should be considered a bug with Config and an additional check should be added in `nested_update` to handle this edge case.

### What did you expect to happen?

No error

### What actually happened?

```py
Traceback (most recent call last):
File "", line 4, in func
return await c.all()
^^^^^^^^^^^^^
File "\redbot\core\config.py", line 307, in _get
return self.nested_update(raw, default)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\redbot\core\config.py", line 553, in nested_update
result = self.nested_update(value, defaults.get(key, {}))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "\redbot\core\config.py", line 556, in nested_update
defaults[key] = pickle.loads(pickle.dumps(current[key], -1))
~~~~~~~~^^^^^
TypeError: 'NoneType' object does not support item assignment
```

### How can we reproduce this error?

Example of broken code
```py
config.register_global(testvar=None)
await config.testvar.set({"a": 4})
return await config.all() # Errors
```

Example alternative that does not break (not mixing groups and values)
```py
config.register_global(testvar={})
await config.testvar.set({"a": 4})
return await config.all() # Works
```

This issue applies to values at all depths
```py
cconfig.register_global(testvar={"b": None})
await config.testvar.set({"a": 4, "b": {"c": 56}})
return await config.all() # Errors
```

### Anything else?

Found by unknown

Discussion for reference:
https://discord.com/channels/133049272517001216/160386989819035648/1467179303262486613
https://discord.com/channels/133049272517001216/171665724262055936/1467617566204891339

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.