cube-js/cube · error

Filter for ${column} is required

Error message

Filter for ${column} is required

What it means

securityFilterFn builds a required 'column IN (...)' filter from security-context values. When no valid values were produced (the coerced kind was 'none' — e.g. 0, NaN, false, null, or an empty array) and the filter was declared required, the compiler refuses to emit a permissive '1 = 1' and throws instead, so the query cannot silently return all rows.

Source

Thrown at packages/cubejs-schema-compiler/src/adapter/MemberSqlTemplateCompiler.js:308

    if (param.kind === 'string') {
      const ph = recordSecurityValue(param.value, state);
      if (typeof column === 'function') return column(ph);
      if (typeof column === 'string') return `${column} = ${ph}`;
      return '';
    }
    if (param.kind === 'vec') {
      if (param.values.length === 0) {
        if (typeof column === 'function') return column([]);
        return '1 = 0';
      }
      const phs = param.values.map(v => recordSecurityValue(v, state));
      if (typeof column === 'function') return column(phs);
      if (typeof column === 'string') return `${column} IN (${phs.join(', ')})`;
      return '';
    }
    // none
    if (required) {
      throw new Error(`Filter for ${column} is required`);
    }
    return '1 = 1';
  };
}

function securityToStringFn(value, state) {
  const values = coerceToStringValue(value);
  return () => {
    if (values === null) return '';
    return values.map(v => recordSecurityValue(v, state)).join(',');
  };
}

function securityContextProxy(value, state) {
  return new Proxy({}, {
    get(_t, prop) {
      if (typeof prop !== 'string') return undefined;
      // Methods coerce the current value lazily — only on access, so reading a

View on GitHub (pinned to 7d981676b3)

Solutions

  1. Verify the security context actually contains the claim the filter references and that it is a valid non-falsy number/boolean.
  2. Use the securityContext entry directly (e.g. securityFilters or ctx['securityContext'].tenantId) instead of a hard-coded 0/false value.
  3. Make the filter optional if an empty result ('1 = 1') is acceptable by setting required to false in the template call.
  4. Fix upstream auth so every token carries the required tenant/organization claim before queries compile.

Example fix

// before
throwing setup: securityContext value { tenantId: 0 } with required filter
// after
securityContext: ctx => ({ tenantId: ctx.tenant_id ?? -1 }) // ensure a real numeric value is always present
Defensive patterns

Strategy: validation

Validate before calling

const val = securityContext?.tenantId;
if (val === undefined || val === null || val === 0 || val === false || Number.isNaN(val)) {
  throw new Error(`Required security filter value missing/falsy for tenantId: ${JSON.stringify(val)}`);
}

Type guard

const hasRequiredFilterValue = (v: unknown): v is number | true => v === true || (typeof v === 'number' && v !== 0 && !Number.isNaN(v));

Try / catch

try { await cube.query(...); } catch (e) { if (/Filter for .* is required/.test(e.message)) { // reject request: security context claim missing
  return res.status(403).json({ error: 'Missing tenant claim in security context' }); } throw e; }

Prevention

When it happens

Trigger: A required security filter (e.g. { filters: [ { member: 'Cubes.tenantId', operator: 'equals', ... requireFilter: true } ] } via filterable cube params) receives a falsy security-context value such as 0, false, NaN, undefined, or an empty list, so no IN clause values exist.

Common situations: JWT token missing the expected claim so the value resolves to undefined; tenant id legitimately equals 0 but the coercion treats 0 as 'none'; misconfigured securityContext path so the value never materializes.

Related errors


AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02). Data as JSON: /api/errors/b69295e62ede054b. Report an issue: GitHub.