cube-js/cube · error · UserError
maskedMembers cannot be provided in the query
Error message
maskedMembers cannot be provided in the query
What it means
Cube's REST API rejects any query body containing a `maskedMembers` property. maskedMembers is an internal mechanism used to hide member-level data based on security contexts; it must be computed server-side, never supplied by the client. Sending it from the client is treated as an attempt to bypass security masking, so the gateway fails fast with a UserError before normalizing the query.
Source
Thrown at packages/cubejs-api-gateway/src/gateway.ts:1448
const startTime = new Date().getTime();
const compilerApi = await this.getCompilerApi(context);
const queryNormalizationResult: Array<{
normalizedQuery: NormalizedQuery,
hasExpressionsInQuery: boolean
}> = queries.map((currentQuery) => {
const hasExpressionsInQuery = this.hasExpressionsInQuery(currentQuery);
if (hasExpressionsInQuery) {
if (!memberExpressions) {
throw new Error('Expressions are not allowed in this context');
}
currentQuery = this.parseMemberExpressionsInQuery(currentQuery);
}
if ((currentQuery as any).maskedMembers) {
throw new UserError('maskedMembers cannot be provided in the query');
}
return {
normalizedQuery: (normalizeQuery(currentQuery, persistent, cacheMode)),
hasExpressionsInQuery
};
});
let normalizedQueries: NormalizedQuery[] = await Promise.all(
queryNormalizationResult.map(
async ({ normalizedQuery, hasExpressionsInQuery }) => {
let evaluatedQuery: Query | NormalizedQuery = normalizedQuery;
if (hasExpressionsInQuery) {
// We need to parse/eval all member expressions early as applyRowLevelSecurity
// needs to access the full SQL query in order to evaluate rules
evaluatedQuery = this.evalMemberExpressionsInQuery(normalizedQuery);
}View on GitHub (pinned to 7d981676b3)
Solutions
- Remove the `maskedMembers` key from the query object before sending it to the API.
- Sanitize queries captured from internal traffic/logs: keep only public fields (measures, dimensions, timeDimensions, filters, segments, order, limit, offset).
- If you need member masking, configure it server-side via security contexts / member visibility so Cube computes maskedMembers itself.
Example fix
// before
await cubeApi.load({ maskedMembers: ['orders.total'], measures: ['orders.count'] });
// after
await cubeApi.load({ measures: ['orders.count'] }); Defensive patterns
Strategy: validation
Validate before calling
const PUBLIC_QUERY_KEYS = ['measures','dimensions','timeDimensions','segments','filters','order','limit','offset','timezone','renewQuery','ungrouped'];
function isQuerySafe(q) { return q != null && Object.keys(q).every(k => PUBLIC_QUERY_KEYS.includes(k)); }
if (!isQuerySafe(query)) throw new Error('Query contains internal fields like maskedMembers'); Type guard
function hasMaskedMembers(q: unknown): q is { maskedMembers: unknown } {
return typeof q === 'object' && q !== null && 'maskedMembers' in q;
} Try / catch
try {
await cubeApi.load(query);
} catch (e) {
if (String(e?.message).includes('maskedMembers')) {
const { maskedMembers, ...clean } = query;
await cubeApi.load(clean); // retry without internal fields
} else throw e;
} Prevention
- Never replay queries captured from internal SQL API traffic or server logs verbatim.
- Serialize queries through a whitelist of public fields before sending.
- Keep the official client SDK; it does not emit maskedMembers.
When it happens
Trigger: POST /cubejs-api/v1/load (or /v1/sql) with a query JSON object that includes a `maskedMembers` key; the check runs in getNormalizedQueries after member expression parsing whenever (currentQuery as any).maskedMembers is truthy.
Common situations: Copying a query captured from Cube's internal/SQL API traffic (which includes maskedMembers) and replaying it against the REST API; saving a serialized query from a debug log or IDE devtools dump that included internal fields; older or hand-written integrations that mirrored server-normalized query objects.
Related errors
- Can't parse date: '${from}'
- Can't parse date: '${to}'
- Can't parse date: '${dateString}'
- Invalid query format: ${error.message || error.toString()}
- No job description provided
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/f24aa4264f9fe602.
Report an issue: GitHub.