{"record":{"id":"d2b356b39816a91d","repo":"elastic/elasticsearch","slug":"variable-doc-must-be-used-with-a-specific-field","errorCode":null,"errorMessage":"Variable 'doc' must be used with a specific field like: doc['myfield']","messagePattern":"Variable 'doc' must be used with a specific field like: doc\\['myfield'\\]","errorType":"validation","errorClass":"ParseException","httpStatus":null,"severity":"error","filePath":"modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java","lineNumber":405,"sourceCode":"        StringBuilder pointer = new StringBuilder();\n        if (cause instanceof ParseException) {\n            int offset = ((ParseException) cause).getErrorOffset();\n            for (int i = 0; i < offset; i++) {\n                pointer.append(' ');\n            }\n        }\n        pointer.append(\"^---- HERE\");\n        stack.add(pointer.toString());\n        throw new ScriptException(message, cause, stack, source, NAME);\n    }\n\n    private static DoubleValuesSource getDocValueSource(String variable, SearchLookup lookup) throws ParseException {\n        VariableContext[] parts = VariableContext.parse(variable);\n        if (parts[0].text.equals(\"doc\") == false) {\n            throw new ParseException(\"Unknown variable [\" + parts[0].text + \"]\", 0);\n        }\n        if (parts.length < 2 || parts[1].type != VariableContext.Type.STR_INDEX) {\n            throw new ParseException(\"Variable 'doc' must be used with a specific field like: doc['myfield']\", 3);\n        }\n\n        // .value is the default for doc['field'], its optional.\n        String variablename = \"value\";\n        String methodname = null;\n        if (parts.length == 3) {\n            if (parts[2].type == VariableContext.Type.METHOD) {\n                methodname = parts[2].text;\n            } else if (parts[2].type == VariableContext.Type.MEMBER) {\n                variablename = parts[2].text;\n            } else {\n                throw new IllegalArgumentException(\n                    \"Only member variables or member methods may be accessed on a field when not accessing the field directly\"\n                );\n            }\n        }\n        // true if the variable is of type doc['field'].date.xxx\n        boolean dateAccessor = false;","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java#L387-L423","documentation":"Thrown in getDocValueSource() when the variable starts with 'doc' but the second segment is not a string-indexed field name (i.e., not in the form doc['fieldname']). The parser expects VariableContext.Type.STR_INDEX for the field specifier, which means bracket notation with a quoted string.","triggerScenarios":"Using 'doc' without bracket-notation field access — e.g., doc.price (dot notation), doc (bare), or doc[price] (unquoted). The expression engine requires doc['fieldname'] syntax specifically.","commonSituations":"Developers familiar with Painless syntax attempting dot-notation access (doc.price) in expressions; missing quotes around the field name; copy-paste from Painless examples.","solutions":["Use bracket notation with single quotes: doc['myfield'] not doc.myfield.","Ensure the field name is enclosed in single quotes inside the brackets.","For method access on fields, use doc['myfield'].value or doc['myfield'].methodName() — the field itself is always bracket-accessed."],"exampleFix":"// before: dot notation is not valid in expressions\n\"source\": \"doc.price.value\"\n// after: bracket notation with single quotes\n\"source\": \"doc['price'].value\"","handlingStrategy":"validation","validationCode":"// Validate that field access uses bracket notation with single quotes\n// Correct: doc['fieldname']\n// Incorrect: doc.fieldname, doc[\"fieldname\"], doc[fieldname]\n// Simple regex check:\n// Pattern: doc\\['[\\w.]+'\\]\nString exprSource = \"doc['price'].value\";\nif (!exprSource.matches(\".*doc\\['[^']+'\\].*\")) {\n    // Warn: field access should use doc['fieldname'] syntax\n}","typeGuard":null,"tryCatchPattern":"try {\n    engine.compile(scriptName, scriptSource, context, params);\n} catch (ScriptException e) {\n    if (e.getCause() instanceof ParseException\n        && e.getCause().getMessage().contains(\"must be used with a specific field\")) {\n        logger.error(\"Use doc['fieldname'] bracket notation, not dot notation\");\n    }\n    throw e;\n}","preventionTips":["Always use doc['fieldname'] with single quotes — never doc.fieldname.","Remember expression syntax differs from Painless — bracket notation is mandatory for field access.","Create a code snippet or template with correct doc[] syntax for team reference.","Lint expression sources for dot-notation field access before deployment."],"tags":["expression","script","syntax","field-access","doc"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}