microsoft/semantic-kernel · error · TypeError

AllowedCallersClaimsValidator: config object cannot be None.

Error message

AllowedCallersClaimsValidator: config object cannot be None.

What it means

A TypeError raised by AllowedCallersClaimsValidator's constructor when the passed config object is falsy (None, empty). The validator needs a Config instance to read the ALLOWED_CALLERS list, so a null config is a programming error rather than a runtime condition.

Source

Thrown at python/samples/demos/copilot_studio_skill/src/api/auth.py:15

# Copyright (c) Microsoft. All rights reserved.

# See https://github.com/microsoft/BotBuilder-Samples/blob/main/samples/python/80.skills-simple-bot-to-bot/echo-skill-bot/authentication/allowed_callers_claims_validator.py
from collections.abc import Awaitable, Callable

from botframework.connector.auth import JwtTokenValidation, SkillValidation
from config import Config


class AllowedCallersClaimsValidator:
    config_key = "ALLOWED_CALLERS"

    def __init__(self, config: Config):
        if not config:
            raise TypeError("AllowedCallersClaimsValidator: config object cannot be None.")

        # ALLOWED_CALLERS is the setting in config.py file
        # that consists of the list of parent bot ids that are allowed to access the skill
        # to add a new parent bot simply go to the AllowedCallers and add
        # the parent bot's microsoft app id to the list
        caller_list = getattr(config, self.config_key)
        if caller_list is None:
            raise TypeError(f'"{self.config_key}" not found in configuration.')
        self._allowed_callers = frozenset(caller_list)

    @property
    def claims_validator(self) -> Callable[[list[dict]], Awaitable]:
        async def allow_callers_claims_validator(claims: dict[str, object]):
            # if allowed_callers is None we allow all calls
            if "*" not in self._allowed_callers and SkillValidation.is_skill_claim(claims):
                # Check that the appId claim in the skill request is in the list of skills configured for this bot.
                app_id = JwtTokenValidation.get_app_id_from_claims(claims)
                if app_id not in self._allowed_callers:

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Pass a fully constructed Config instance: AllowedCallersClaimsValidator(config).
  2. Ensure config = Config(); config.validate() runs before the validator is created.
  3. Guard the call site: construct the validator only after confirming config is not None.

Example fix

// before
validator = AllowedCallersClaimsValidator(None)

// after
from config import config
validator = AllowedCallersClaimsValidator(config)
Defensive patterns

Strategy: type-guard

Validate before calling

from config import config
assert config is not None, "Config must be initialized before building the validator"
validator = AllowedCallersClaimsValidator(config)

Type guard

from config import Config

def is_valid_config(c) -> bool:
    return isinstance(c, Config) and bool(c)

Prevention

When it happens

Trigger: Instantiating AllowedCallersClaimsValidator(config) with config=None or an otherwise falsy value, typically a wiring/DI mistake in the bot startup code.

Common situations: The Config singleton wasn't initialized before constructing the validator; a refactor passed None by mistake; import order caused config to be unavailable at construction.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/021391e7c2955a1d. Report an issue: GitHub.