dianping/cat · error · StaticError
XPST0008
XPST0008
Error message
"{name}": undeclared variable What it means
XPST0008 here reports a reference to an undeclared variable. addVarRef() walks the parent static-context chain via getVariable(); if no declaration is found it errors only when qname.uri === '' (unqualified names must resolve locally) or when a moduleResolver is present (imported modules' variables are expected to be resolvable, so an unknown name is a real error). Variables in foreign namespaces are skipped when no resolver exists because they may come from unimported modules.
Source
Thrown at cat-home/src/main/webapp/assets/js/editor/worker-xquery.js:1943
}
return variables;
},
getVariable: function(qname) {
var key = getVarKey(qname);
var that = this;
while(that) {
if(that.variables[key]) {
return that.variables[key];
}
that = that.parent;
}
},
addVarRef: function(qname, pos){
var varDecl = this.getVariable(qname);
if(!varDecl && (qname.uri === '' || this.root.moduleResolver)) {
throw new StaticError('XPST0008', '"' + qname.name + '": undeclared variable', pos);
}
var key = getVarKey(qname);
this.varRefs[key] = true;
},
addFunctionCall: function(qname, arity, pos){
var fn = this.getFunction(qname, arity);
if(!fn && (qname.uri === 'http://www.w3.org/2005/xquery-local-functions' || this.root.moduleResolver)){
if((qname.uri === 'http://www.w3.org/2005/xpath-functions' ||
(qname.uri === '' && this.root.defaultFunctionNamespaces.concat(this.root.defaultFunctionNamespace).indexOf('http://www.w3.org/2005/xpath-functions') !== -1)) && qname.name === 'concat') {
} else if(!fn){
throw new StaticError('XPST0008', '"' + qname.name + '#' + arity + '": undeclared function', pos);
}
}
var key = getFnKey(qname, arity);
this.functionCalls[key] = true;
},
View on GitHub (pinned to e815e74d4c)
Solutions
- Declare the variable: 'declare variable $foo := ...;' before use.
- Fix the reference typo to match the declared name exactly (XQuery names are case-sensitive).
- If it comes from a module, import that module and confirm the resolver merges its variables into the static context.
- Check spelling of the prefix — a wrong prefix yields a different expanded QName.
Example fix
// before let $r := $resultCount return $r (: nothing declares $resultCount :) // after declare variable $resultCount as xs:integer := 42; let $r := $resultCount return $r
Defensive patterns
Strategy: validation
Validate before calling
// Before analysis: every referenced variable must have a declaration or module source
varRefs.forEach(function(ref) {
if (!declaredVars[ref.uri + '#' + ref.name] &&
!(ref.uri !== '' && !hasModuleResolver)) {
warn('Undeclared variable $' + ref.name);
}
}); Type guard
function isDeclaredVariable(ctx, qname) {
return !!ctx.getVariable(qname); // walks parent static contexts
} Try / catch
if (e.code === 'XPST0008' && /variable/.test(e.message)) {
highlight(e.pos, 'Declare the variable or fix the name — names are case-sensitive');
} Prevention
- Declare variables before referencing them in document order.
- When importing modules for their variables, confirm the resolver merges mod.variables.
- Use editor autocomplete over declared names to avoid typos.
When it happens
Trigger: Referencing $foo in the query body with no matching declare variable / import of its module (unqualified case), or referencing $mod:var when a moduleResolver is configured but the imported module does not export that variable.
Common situations: Typos in variable names; using a variable declared in a different module without importing it; deleting a declaration but leaving references; module resolver returning a module whose variables list doesn't cover the referenced name.
Related errors
AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14).
Data as JSON: /api/errors/2ac960815420df4e.
Report an issue: GitHub.