{"record":{"id":"9b9609f674b0140d","repo":"apache/beam","slug":"f-unknown-log-level-level-not-in-list-log-levels-keys","errorCode":null,"errorMessage":"f'Unknown log level {level} not in {list(log_levels.keys())}'","messagePattern":"f'Unknown log level (.+?) not in (.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/yaml/yaml_provider.py","lineNumber":1197,"sourceCode":"    The output of this transform is a copy of its input for ease of use in\n    chain-style pipelines.\n\n    Args:\n      level: one of ERROR, INFO, or DEBUG, mapped to a corresponding\n        language-specific logging level\n      prefix: an optional identifier that will get prepended to the element\n        being logged\n    \"\"\"\n    # Keeping this simple to be language agnostic.\n    # The intent is not to develop a logging library (and users can always do)\n    # their own mappings to get fancier output.\n    log_levels = {\n        'ERROR': logging.error,\n        'INFO': logging.info,\n        'DEBUG': logging.debug,\n    }\n    if level not in log_levels:\n      raise ValueError(\n          f'Unknown log level {level} not in {list(log_levels.keys())}')\n    logger = log_levels[level]\n\n    def to_loggable_json_recursive(o):\n      if isinstance(o, (str, bytes)):\n        return str(o)\n      elif callable(getattr(o, '_asdict', None)):\n        return to_loggable_json_recursive(o._asdict())\n      elif isinstance(o, Mapping) and callable(getattr(o, 'items', None)):\n        return {str(k): to_loggable_json_recursive(v) for k, v in o.items()}\n      elif isinstance(o, Iterable):\n        return [to_loggable_json_recursive(x) for x in o]\n      else:\n        return o\n\n    def log_and_return(x):\n      logger(prefix + json.dumps(to_loggable_json_recursive(x)))\n      return x","sourceCodeStart":1179,"sourceCodeEnd":1215,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/yaml/yaml_provider.py#L1179-L1215","documentation":"The YAML Log transform maps a language-agnostic log level to logging calls, but recognizes only ERROR, INFO, and DEBUG; the level given matches none of them, so it rejects the configuration rather than silently choosing a default.","triggerScenarios":"Setting level: WARNING, level: error (lowercase), level: FATAL, or any other value outside {'ERROR','INFO','DEBUG'} in the YAML logging transform config.","commonSituations":"Authors assume all Python logging levels are supported (WARNING/CRITICAL are not mapped), or use lowercase level names.","solutions":["Use exactly one of 'ERROR', 'INFO', or 'DEBUG' (uppercase).","Map unsupported levels yourself: use 'ERROR' for WARNING/CRITICAL-level output or preprocess the level string with .upper().","Extend the config upstream so only supported levels are offered."],"exampleFix":"# before\n- type: LogForLevel\n  config:\n    level: warning\n# after\n- type: LogForLevel\n  config:\n    level: ERROR","handlingStrategy":"validation","validationCode":"VALID_LOG_LEVELS = {'ERROR', 'INFO', 'DEBUG'}\ndef validate_log_level(level):\n    if str(level).upper() not in VALID_LOG_LEVELS:\n        raise ValueError(f'level must be one of {sorted(VALID_LOG_LEVELS)}')","typeGuard":"def is_supported_log_level(level):\n    return isinstance(level, str) and level in {'ERROR', 'INFO', 'DEBUG'}","tryCatchPattern":"try:\n    level_fn = {'ERROR': logging.error, 'INFO': logging.info, 'DEBUG': logging.debug}[level]\nexcept KeyError:\n    logging.warning('Unsupported level %r, falling back to INFO', level)\n    level_fn = logging.info","preventionTips":["Restrict offered levels in config tooling to ERROR/INFO/DEBUG.","Normalize case (level.upper()) before passing the config through, since matching is case-sensitive.","Map WARNING/CRITICAL to the closest supported level yourself."],"tags":["python","apache-beam","yaml","logging"],"backgroundTag":"invalid-enum-value","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}