databendlabs/databend · error · ValueError

Token does not belong to this ContextVar

Error message

Token does not belong to this ContextVar

What it means

This is a proc-macro compile-time error from derive(Visit)/derive(WalkMut): the visitor derive supports structs and enums but has no implementation for Rust unions. Applying the derive to a union type aborts compilation with this message at the union's span.

Solutions

  1. Remove the Walk/Visit derive from the union and implement the visitor manually.
  2. Restructure the type as an enum or struct instead of a union.
  3. Wrap the union in a newtype struct/enum that carries a manual Walk impl.

Example fix

// before
#[derive(Visit)]
union Raw { i: u64, f: f64 }
// after
impl<'ast> Visit<'ast> for Raw { /* manual impl */ }
Defensive patterns

Strategy: type-guard

Validate before calling

// compile-time: ensure derive targets are struct or enum
const _: () = { assert!(std::mem::size_of::<MyType>() > 0); }; // cannot detect union at runtime; check the source type before deriving

Prevention

When it happens

Trigger: Annotating a `union` definition with #[derive(Visit)] or #[derive(WalkMut)] in the query AST codebase.

Common situations: Refactoring an enum/struct into a union for FFI or memory-layout reasons while keeping the derive; copy-pasting a derive list onto a new union type.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/e8b5a929e9865fd9. Report an issue: GitHub.

Appendix: source

Thrown at src/query/script_udf_support/src/transform_udf_script.rs:650

            def get(self, default=_MISSING):
                value = getattr(self._local, "value", _MISSING)
                if value is _MISSING:
                    if default is not _MISSING:
                        return default
                    if self.default is _MISSING:
                        raise LookupError(f"ContextVar {self.name} has no value")
                    return self.default
                return value

            def set(self, value):
                old = getattr(self._local, "value", _MISSING)
                self._local.value = value
                return Token(self, old)

            def reset(self, token):
                if token.var is not self:
                    raise ValueError("Token does not belong to this ContextVar")
                if token.old is _MISSING:
                    if hasattr(self._local, "value"):
                        del self._local.value
                else:
                    self._local.value = token.old

        class Context:
            def __init__(self, values=None):
                self._values = values or {}

            def __setitem__(self, key, value):
                self._values[key] = value

            def items(self):
                return self._values.items()

            def run(self, callable, *args, **kwargs):
                tokens = []

View on GitHub (pinned to 288d84d76e)