pallets/flask · error · KeyError
Tag ' ' is already registered.
Error message
Tag '{key}' is already registered. What it means
TaggedJSONSerializer.register(tag_class) instantiates the tag, reads tag.key, and if key is truthy and already present in self.tags (and force=False), raises KeyError. This protects session/tag serialization from two tags claiming the same key, which would make encoded data ambiguous.
Solutions
- Choose a unique key for your custom JSONTag that does not collide with existing tags.
- Pass force=True to register() if you intentionally want to override an existing tag.
- Inspect app.session_interface.serializer.tags keys before registering to detect collisions.
Example fix
# before
class MyTag(JSONTag):
key = 'list' # collides with built-in
app.session_interface.serializer.register(MyTag) # KeyError
# after
class MyTag(JSONTag):
key = 'mylist'
app.session_interface.serializer.register(MyTag)
# or override: register(MyTag, force=True) Defensive patterns
Strategy: validation
Validate before calling
def tag_key_available(serializer, key: str) -> bool:
return key not in serializer.tags Type guard
def is_unique_tag_key(serializer, key: str) -> bool:
return key not in serializer.tags Try / catch
try:
serializer.register(MyTag)
except KeyError as e:
if 'already registered' in str(e):
serializer.register(MyTag, force=True)
else:
raise Prevention
- Inspect serializer.tags.keys() before registering a custom tag.
- Use a distinctive key namespace for custom tags to avoid collisions.
When it happens
Trigger: Registering a custom JSONTag whose key collides with a built-in tag key (e.g. ' di', 'list', 'tuple') or with another custom tag already registered, without passing force=True. The dict self.tags maps key->tag and a duplicate would overwrite silently.
Common situations: Extending session serialization with a custom tag and accidentally reusing an existing key. Loading a Flask extension that registers a tag also registered by another extension. Upgrading Flask where a new built-in tag key now collides with your custom one.
Related errors
- Object of type is not JSON serializable
- Session backend did not open a session.
- The session is unavailable because no secret key was set. …
- A valid Flask application was not obtained from
- Allowed methods must be a list of strings, for example…
AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11).
Data as JSON: /api/errors/e6e5f55392cffdaf.
Report an issue: GitHub.
Appendix: source
Thrown at src/flask/json/tag.py:280
"""Register a new tag with this serializer.
:param tag_class: tag class to register. Will be instantiated with this
serializer instance.
:param force: overwrite an existing tag. If false (default), a
:exc:`KeyError` is raised.
:param index: index to insert the new tag in the tag order. Useful when
the new tag is a special case of an existing tag. If ``None``
(default), the tag is appended to the end of the order.
:raise KeyError: if the tag key is already registered and ``force`` is
not true.
"""
tag = tag_class(self)
key = tag.key
if key:
if not force and key in self.tags:
raise KeyError(f"Tag '{key}' is already registered.")
self.tags[key] = tag
if index is None:
self.order.append(tag)
else:
self.order.insert(index, tag)
def tag(self, value: t.Any) -> t.Any:
"""Convert a value to a tagged representation if necessary."""
for tag in self.order:
if tag.check(value):
return tag.tag(value)
return value
def untag(self, value: dict[str, t.Any]) -> t.Any:
"""Convert a tagged representation back to the original type."""View on GitHub (pinned to 3596b1ab61)