FoundationAgents/MetaGPT · warning · AttributeError

No such attribute: {key}

Error message

No such attribute: {key}

What it means

metagpt Context uses plain __dict__ storage with permissive __getattr__ (unknown reads return None) but a strict __delattr__: deleting a key not present in self.__dict__ raises AttributeError 'No such attribute: {key}'. This asymmetry means reads never fail while deletes do, catching typos at cleanup time.

Source

Thrown at metagpt/context.py:45

    """A dict-like object that allows access to keys as attributes, compatible with Pydantic."""

    model_config = ConfigDict(extra="allow")

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.__dict__.update(kwargs)

    def __getattr__(self, key):
        return self.__dict__.get(key, None)

    def __setattr__(self, key, value):
        self.__dict__[key] = value

    def __delattr__(self, key):
        if key in self.__dict__:
            del self.__dict__[key]
        else:
            raise AttributeError(f"No such attribute: {key}")

    def set(self, key, val: Any):
        self.__dict__[key] = val

    def get(self, key, default: Any = None):
        return self.__dict__.get(key, default)

    def remove(self, key):
        if key in self.__dict__:
            self.__delattr__(key)


class Context(BaseModel):
    """Env context for MetaGPT"""

    model_config = ConfigDict(arbitrary_types_allowed=True)

    kwargs: AttrDict = AttrDict()

View on GitHub (pinned to 11cdf466d0)

Solutions

  1. Use Context.remove(key) instead of del — it checks membership first and silently does nothing when absent.
  2. Guard deletes: if key in ctx.__dict__: del ctx.__dict__[key].
  3. Fix the key name typo revealed by the message.

Example fix

# before
del ctx.options['reuseable']   # wrong/absent key -> AttributeError

# after
ctx.remove('reusable')           # no-op if missing
Defensive patterns

Strategy: type-guard

Validate before calling

if key in ctx.__dict__:
    del ctx.__dict__[key]
# or simply: ctx.remove(key)  which is already membership-guarded

Type guard

def has_context_key(ctx: Context, key: str) -> bool:
    return key in ctx.__dict__

Prevention

When it happens

Trigger: Calling del context.some_key, context.__delattr__('x'), or context.remove('x') (remove delegates to __delattr__) for a key that was never set or was already deleted.

Common situations: Cleanup code that deletes optional keys unconditionally; double-delete in retry loops; typo'd key names; assuming getattr-returns-None semantics imply delete is also lenient.

Related errors


AI-assisted analysis of FoundationAgents/MetaGPT@11cdf466d0 (2026-08-14). Data as JSON: /api/errors/2e27add8f2ad9389. Report an issue: GitHub.