github/spec-kit · error · EventRefreshError

failures

Error message

failures

What it means

EventRefreshError is raised after a batch refresh of event configs across installed extensions/integrations: each per-extension failure was caught, logged as a warning ('Failed to refresh events for ...'), and accumulated into a `failures` list of (key, message) tuples; if any failed, the whole refresh aborts with this error. It is an aggregation wrapper, not a single root cause — inspect the pairs inside.

Source

Thrown at src/specify_cli/events.py:1770

            # is both unsafe and redundant.
            # S7: resolve this integration's persisted parsed_options so a
            # stored --events false is honored across extension lifecycle
            # changes; passing None would re-enable events the user disabled.
            _, parsed_options = _resolve_integration_options(integration, state, key, None)
            events_map = resolve_events(
                key, integration.config, project_root, parsed_options
            )
            # install_integration_events handles both the populated case
            # (writes new config, stripping stale owned entries) and the empty
            # case (strips prior hooks for --events false / disabled override).
            install_integration_events(integration, project_root, manifest, events_map)
            manifest.save()
        except Exception as exc:
            logger.warning("Failed to refresh events for '%s': %s", key, exc)
            failures.append((key, str(exc)))

    if failures:
        raise EventRefreshError(failures)


# -- Manifest validation ---------------------------------------------------

def validate_events(data: dict[str, Any]) -> None:
    """Validate ``events`` field in extension manifest data."""
    from .extensions import ValidationError

    events = data.get("events")
    if "events" in data and not isinstance(events, dict):
        raise ValidationError("Invalid events: expected a mapping")
    if events:
        for event_name, event_config in events.items():
            if not isinstance(event_config, dict):
                raise ValidationError(
                    f"Invalid event '{event_name}': expected a mapping"
                )
            command = event_config.get("command")

View on GitHub (pinned to bf88c9f9a8)

Solutions

  1. Read the (key, message) pairs in the exception payload and the preceding log warnings to identify which integration failed and why.
  2. Fix the root cause for that key (e.g. correct the extension's events mapping, repair permissions, remove a rogue symlink).
  3. Re-run the refresh; extensions are processed independently so fixing the one bad entry clears the error.
  4. If a stale/broken extension is the cause, uninstall it (`specify extension uninstall <key>`) and refresh again.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    refresh_installed_extension_events(project_root)
except EventRefreshError as e:
    for key, msg in e.failures:  # (integration_key, root_cause) pairs
        logger.error("events refresh failed for %s: %s", key, msg)
    # proceed / report — root causes are independent per extension

Prevention

When it happens

Trigger: Calling refresh_installed_extension_events (event refresh pass after install/update/uninstall): for one or more integration keys, resolve_events or install_integration_events raised any Exception; each is appended to failures and re-raised as EventRefreshError(failures).

Common situations: One extension's manifest has invalid events config (bad command, unknown event name, non-string matcher); a destination file is unwritable or symlinked (see the symlink guard); partial uninstall left a stale manifest pointing at missing files.

Related errors


AI-assisted analysis of github/spec-kit@bf88c9f9a8 (2026-08-14). Data as JSON: /api/errors/fa58cd8e06ac90ae. Report an issue: GitHub.