{"record":{"id":"a0a6f35e977654fb","repo":"mybatis/mybatis-3","slug":"could-not-find-sql-statement-to-include-with-refid","errorCode":null,"errorMessage":"Could not find SQL statement to include with refid '{refid}'","messagePattern":"Could not find SQL statement to include with refid '(.+?)'","errorType":"exception","errorClass":"IncompleteElementException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/builder/xml/XMLIncludeTransformer.java","lineNumber":101,"sourceCode":"      NodeList children = source.getChildNodes();\n      for (int i = 0; i < children.getLength(); i++) {\n        applyIncludes(children.item(i), variablesContext, included);\n      }\n    } else if (included && (source.getNodeType() == Node.TEXT_NODE || source.getNodeType() == Node.CDATA_SECTION_NODE)\n        && !variablesContext.isEmpty()) {\n      // replace variables in text node\n      source.setNodeValue(PropertyParser.parse(source.getNodeValue(), variablesContext));\n    }\n  }\n\n  private Node findSqlFragment(String refid, Properties variables) {\n    refid = PropertyParser.parse(refid, variables);\n    refid = builderAssistant.applyCurrentNamespace(refid, true);\n    try {\n      XNode nodeToInclude = configuration.getSqlFragments().get(refid);\n      return nodeToInclude.getNode().cloneNode(true);\n    } catch (IllegalArgumentException e) {\n      throw new IncompleteElementException(\"Could not find SQL statement to include with refid '\" + refid + \"'\", e);\n    }\n  }\n\n  private String getStringAttribute(Node node, String name) {\n    return node.getAttributes().getNamedItem(name).getNodeValue();\n  }\n\n  /**\n   * Read placeholders and their values from include node definition.\n   *\n   * @param node\n   *          Include node instance\n   * @param inheritedVariablesContext\n   *          Current context used for replace variables in new variables values\n   *\n   * @return variables context from include instance (no inherited values)\n   */\n  private Properties getVariablesContext(Node node, Properties inheritedVariablesContext) {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/builder/xml/XMLIncludeTransformer.java#L83-L119","documentation":"Thrown by XMLIncludeTransformer.findSqlFragment() when an <include refid=\"...\"/> in a mapper XML cannot resolve to any <sql id=\"...\"/> fragment. The refid is first expanded for ${} variables and then qualified with the current namespace, so both the fragment's existence and its fully-qualified name must match. It is wrapped as IncompleteElementException, which the builder may retry later (parsePending) before failing permanently.","triggerScenarios":"<include refid=\"cols\"/> where no <sql id=\"cols\"> exists in the same namespace and no fully-qualified refid='com.acme.UserMapper.cols' fragment exists; a refid built from a ${variable} that resolves to an unexpected value; a <sql> fragment defined in a mapper that itself failed to load (bad XML, missing from <mappers>).","commonSituations":"Renaming or deleting a shared <sql> fragment but not the <include> references; moving mappers between packages and forgetting that unqualified refids resolve only within the same namespace; circular mapper includes; a typo in refid; the fragment lives in a mapper XML that was never registered in <mappers>.","solutions":["Define a matching <sql id=\"...\"> in the same mapper namespace, or qualify the refid with the owning namespace (refid=\"com.acce.CommonMapper.baseCols\")","Check the refid for typos and for ${variable} substitutions whose runtime values differ from what you expect","Ensure the mapper XML that declares the fragment is actually registered in <mappers> and parses cleanly (a failed mapper leaves pending includes that surface as this error)"],"exampleFix":"<!-- before -->\n<sql id=\"baseColumns\">id, name</sql>\n<select id=\"findAll\">SELECT <include refid=\"baseColums\"/> FROM user</select>\n\n<!-- after -->\n<sql id=\"baseColumns\">id, name</sql>\n<select id=\"findAll\">SELECT <include refid=\"baseColumns\"/> FROM user</select>","handlingStrategy":"validation","validationCode":"// after parsing, before use: verify every include refid resolves\nSet<String> ids = sqlFragments.keySet(); // qualified ids like 'ns.cols'\nfor (String refid : includeRefids) {\n  String qualified = refid.contains(\".\") ? refid : namespace + \".\" + refid;\n  if (!ids.contains(qualified)) throw new IllegalStateException(\"Unresolvable include refid: \" + refid);\n}","typeGuard":null,"tryCatchPattern":"catch (PersistenceException e) { if (e.getCause() instanceof IncompleteElementException) report missing fragment refid; } — but prefer fixing the mapper XML; the builder already retries pending includes.","preventionTips":["Keep <sql> fragments and their <include> refs in one review unit","Prefer fully-qualified refids for cross-mapper fragments","Run a smoke test that builds the SqlSessionFactory in CI to catch pending includes"],"tags":["mybatis","mapper-xml","sql-fragment","include"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}