{"record":{"id":"55cb24d08c68c62d","repo":"elastic/elasticsearch","slug":"variable-does-not-follow-an-allowed-format-of","errorCode":null,"errorMessage":"Variable [{}] does not follow an allowed format of either doc['field'] or doc['field'].method()","messagePattern":"Variable \\[(.+?)\\] does not follow an allowed format of either doc\\['field'\\] or doc\\['field'\\]\\.method\\(\\)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java","lineNumber":436,"sourceCode":"                    \"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;\n        if (parts.length > 3) {\n            // access to the .date \"object\" within the field\n            if (parts.length == 4 && (\"date\".equals(parts[2].text) || \"getDate\".equals(parts[2].text))) {\n                if (parts[3].type == VariableContext.Type.METHOD) {\n                    methodname = parts[3].text;\n                    dateAccessor = true;\n                } else if (parts[3].type == VariableContext.Type.MEMBER) {\n                    variablename = parts[3].text;\n                    dateAccessor = true;\n                }\n            }\n            if (dateAccessor == false) {\n                throw new IllegalArgumentException(\n                    \"Variable [\" + variable + \"] does not follow an allowed format of either doc['field'] or doc['field'].method()\"\n                );\n            }\n        }\n\n        String fieldname = parts[1].text;\n        MappedFieldType fieldType = lookup.fieldType(fieldname);\n\n        if (fieldType == null) {\n            throw new ParseException(\"Field [\" + fieldname + \"] does not exist in mappings\", 5);\n        }\n\n        IndexFieldData<?> fieldData = lookup.getForField(fieldType, MappedFieldType.FielddataOperation.SEARCH);\n        final DoubleValuesSource valueSource;\n        if (fieldType instanceof GeoPointFieldType) {\n            // geo\n            if (methodname == null) {\n                valueSource = GeoField.getVariable(fieldData, fieldname, variablename);","sourceCodeStart":418,"sourceCodeEnd":454,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-expression/src/main/java/org/elasticsearch/script/expression/ExpressionScriptEngine.java#L418-L454","documentation":"Thrown in getDocValueSource() when the variable has more than 3 parts and does not match the date accessor pattern (doc['field'].date.xxx or doc['field'].getDate.xxx). The only valid 4-part form is date object access; anything else triggers this error.","triggerScenarios":"Chaining more than one accessor on a field in an unsupported way — e.g., doc['field'].value.foo or doc['field'].lat.lon. Only doc['field'].date.<member/method> is valid for 4-part paths.","commonSituations":"Attempting nested property access that isn't supported; trying to chain geo point accessors (doc['field'].lat.lon instead of doc['field'].lat and doc['field'].lon separately); misunderstanding the date object accessor pattern.","solutions":["Limit field access to at most 3 parts: doc['field'].value or doc['field'].method().","For date accessors, use the 4-part pattern: doc['field'].date.<property> — valid properties include year, month, day, etc.","Split chained access into separate variables in the expression and combine arithmetically.","Switch to Painless for complex nested field access."],"exampleFix":"// before: unsupported chained access\n\"source\": \"doc['location'].lat.lon\"\n// after: access each property separately\n\"source\": \"doc['location'].lat + doc['location'].lon\"","handlingStrategy":"validation","validationCode":"// Validate that chained access beyond doc['field'].member is only for date objects\n// Correct: doc['field'].date.year, doc['field'].getDate.year\n// Incorrect: doc['field'].value.foo, doc['field'].lat.lon\n// Check expression source for paths with more than 3 segments that aren't date accessors","typeGuard":null,"tryCatchPattern":"try {\n    engine.compile(scriptName, scriptSource, context, params);\n} catch (ScriptException e) {\n    if (e.getCause() instanceof IllegalArgumentException\n        && e.getCause().getMessage().contains(\"does not follow an allowed format\")) {\n        logger.error(\"Expression variable format invalid — use doc['field'] or doc['field'].method()\");\n        // The variable name is in the error message\n    }\n    throw e;\n}","preventionTips":["Keep field access paths short: at most doc['field'].member or doc['field'].method().","For date properties, use the 4-part pattern: doc['field'].date.<property>.","Split complex chained access into separate variables and combine arithmetically.","Use Painless for any field access that requires more than simple member/method navigation."],"tags":["expression","script","syntax","field-access","date-accessor"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}