{"record":{"id":"f6cffc1310c487ba","repo":"hibernate/hibernate-orm","slug":"could-not-chain-accessor-because-result-of-previou","errorCode":null,"errorMessage":"Could not chain accessor because result of previous accessor was null","messagePattern":"Could not chain accessor because result of previous accessor was null","errorType":"exception","errorClass":"PropertyAccessException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/property/access/internal/ChainedPropertyAccessImpl.java","lineNumber":62,"sourceCode":"\tpublic Setter getSetter() {\n\t\treturn this;\n\t}\n\n\t@Override\n\tpublic @Nullable Object get(Object owner) {\n\t\t@Nullable Object result = owner;\n\t\tfor ( int i = 0; i < propertyAccesses.length; i++ ) {\n\t\t\tresult = propertyAccesses[i].getGetter().get( NullnessUtil.castNonNull( result ) );\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic @Nullable Object getForInsert(Object owner, Map<Object, Object> mergeMap, SharedSessionContractImplementor session) {\n\t\t@Nullable Object result = owner;\n\t\tfor ( int i = 0; i < propertyAccesses.length; i++ ) {\n\t\t\tif ( result == null ) {\n\t\t\t\tthrow new PropertyAccessException( \"Could not chain accessor because result of previous accessor was null\" );\n\t\t\t}\n\t\t\tresult = propertyAccesses[i].getGetter().getForInsert( result, mergeMap, session );\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void set(Object target, @Nullable Object value) {\n\t\tthrow new UnsupportedOperationException();\n\t}\n\n\t@Override\n\tpublic Class<?> getReturnTypeClass() {\n\t\treturn propertyAccesses[propertyAccesses.length - 1].getGetter().getReturnTypeClass();\n\t}\n\n\t@Override\n\tpublic Type getReturnType() {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/property/access/internal/ChainedPropertyAccessImpl.java#L44-L80","documentation":"ChainedPropertyAccessImpl applies a chain of getters for a dotted property path (nested embeddables). getForInsert walks the chain and throws PropertyAccessException 'Could not chain accessor because result of previous accessor was null' the moment an intermediate link is null, because the next getter cannot be invoked on null. (The plain get() path instead fails on its non-null contract.)","triggerScenarios":"Persisting or flushing an entity whose mapping uses a chained property path (e.g., details.address.city across nested @Embedded values) while an intermediate embeddable instance is null at insert time.","commonSituations":"Embeddables never initialized in constructors or factory methods; builder/DTO-mapping code that skips optional sections and leaves intermediate objects null; inserts that populate only the leaf value; refactoring flat fields into nested embeddables without initializing them.","solutions":["Initialize intermediate embeddables eagerly: private Address address = new Address();","Validate that the full path is populated before persist, or populate missing links in a @PrePersist callback","Flatten the mapping so the leaf is reached without a chain, if null intermediates are legitimate in your domain","Review entity factories and mapping code to always construct the complete embeddable hierarchy"],"exampleFix":"// before\n@Entity public class Customer {\n    @Embedded private Details details; // never initialized\n}\n\n// after\n@Entity public class Customer {\n    @Embedded private Details details = new Details();\n}\n@Embeddable public class Details {\n    @Embedded private Address address = new Address();\n}","handlingStrategy":"validation","validationCode":"if (customer.getDetails() == null || customer.getDetails().getAddress() == null) {\n    throw new IllegalStateException(\"Nested embeddables must be initialized before persist\");\n}\nsession.persist(customer);","typeGuard":null,"tryCatchPattern":"try {\n    session.persist(customer);\n} catch (org.hibernate.PropertyAccessException e) {\n    if (e.getMessage().contains(\"chain accessor\")) {\n        // an intermediate embeddable was null: initialize the chain and retry\n    }\n}","preventionTips":["Initialize nested embeddables in field initializers or constructors","Make entity factories always build the complete embeddable hierarchy","Add @PrePersist to populate missing intermediate embeddables","Cover inserts of chained-path entities in tests"],"tags":["hibernate","embedded","property-access","null-safety","flush"],"backgroundTag":"null-intermediate-embeddable","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}