cube-js/cube · error · UserError
'pre_aggregations' must be a sequence
Error message
'pre_aggregations' must be a sequence
What it means
Cube's YAML data model converter requires the top-level 'pre_aggregations' (or 'preAggregations') key to hold a YAML sequence (list) of pre-aggregation definitions. This library throws when the value under that key is a scalar or a map instead of a list, because it iterates seq.items to extract per-pre-aggregation names.
Source
Thrown at packages/cubejs-schema-compiler/src/compiler/converters/CubePreAggregationConverter.ts:99
protected convertYaml(cubeDefSet: YamlSet) {
const { preAggregationName, code } = this.preAggregationDefinition;
const { cubeDefinition } = cubeDefSet;
const preAggDoc = YAML.parseDocument(code);
const preAggNode = preAggDoc.contents;
if (!preAggNode || !isMap(preAggNode)) {
throw new UserError('Pre-aggregation YAML must be a map/object');
}
const preAggsPair = cubeDefinition.items.find(
(pair: Pair) => isScalar(pair.key) && (pair.key.value === 'pre_aggregations' || pair.key.value === 'preAggregations')
);
if (preAggsPair) {
const seq = preAggsPair.value;
if (!YAML.isSeq(seq)) {
throw new UserError('\'pre_aggregations\' must be a sequence');
}
const exists = seq.items.some(item => {
if (isMap(item)) {
const namePair = item.items.find(
(pair: Pair) => isScalar(pair.key) && pair.key.value === 'name'
);
return namePair && isScalar(namePair.value) && namePair.value.value === preAggregationName;
}
return false;
});
if (exists) {
throw new UserError(`Pre-aggregation '${preAggregationName}' is already defined`);
}
seq.items.push(preAggNode);
} else {View on GitHub (pinned to 7d981676b3)
Solutions
- Rewrite pre_aggregations as a YAML sequence: each pre-aggregation starts with `- ` under the key
- Check indentation — pre_aggregations must be a sibling key of the cube, and its items indented with '- '
- If migrating from JS schema, remember YAML names go inside each item's 'name:' field, not as map keys
Example fix
# before
pre_aggregations:
main:
measures: [visitors.count]
# after
pre_aggregations:
- name: main
measures:
- visitors.count Defensive patterns
Strategy: validation
Validate before calling
function assertPreAggregationsIsList(cube) {
const v = cube.pre_aggregations ?? cube.preAggregations;
if (v != null && !Array.isArray(v)) {
throw new Error("'pre_aggregations' must be a list of pre-aggregation objects");
}
} Type guard
const isPreAggSeq = (v) => Array.isArray(v) || (v && typeof v.items === 'object');
Try / catch
try {
converter.convert(cubeDef);
} catch (e) {
if (e.message.includes("'pre_aggregations' must be a sequence")) {
console.error('Fix YAML: pre_aggregations items must start with "- "');
}
throw e;
} Prevention
- Always prefix each pre-aggregation in YAML with '- '
- Keep JS-style named maps out of YAML models — use 'name:' inside list items
- Lint YAML data models with Cube's compiler in CI to catch shape errors early
When it happens
Trigger: Defining pre_aggregations as a YAML mapping (e.g. `pre_aggregations:\n main: ...`), as a scalar string, or with wrong indentation so the parsed node is not a YAMLSeq, while converting a YAML schema file via CubeSchemaConverter.convertYaml.
Common situations: Hand-written YAML data models where pre_aggregations was indented as a map instead of a list item; copying JS-style named pre-aggregations (`main: {...}`) into YAML without the `- ` list prefix; tabs/indentation errors making the parser see a map.
Related errors
- Can't resolve '${m}'
- Pre-aggregation YAML must be a map/object
- Table names should be in <table> or <schema>.<table> format
- Can't parse date: '${from}'
- Can't parse date: '${to}'
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/d184385e62bcd1f7.
Report an issue: GitHub.