MyCATApache/Mycat-Server · error · SQLNonTransientException

parent key can't find valid datanode ,expect 1 but found

Error message

parent key can't find  valid datanode ,expect 1 but found: {size}

What it means

When inserting into an ER/child table, MyCat computes the target data node by applying the parent table's sharding rule to the join key value. If ruleCalculate returns zero nodes or more than one node, the child row cannot be deterministically placed, so SQLNonTransientException('parent key can't find valid datanode, expect 1 but found: N') is thrown.

Solutions

  1. Ensure the parent key value in the child insert maps to exactly one datanode under the parent's rule (check algorithm calculate() for that value)
  2. Insert the parent row first and use a joinKey value consistent with it
  3. Use a single-node-exact rule (e.g. mod/hash) on the parent table so child routing resolves to one node

Example fix

-- before: parent rule returns null for user_id=9999
INSERT INTO t_order_item (id, order_id, user_id) VALUES (1, 10, 9999);
-- after: use a parent-key value covered by the rule
INSERT INTO t_order_item (id, order_id, user_id) VALUES (1, 10, 100);
Defensive patterns

Strategy: validation

Validate before calling

// before child-table insert
Set<String> dns = ruleCalculate(parentTC, colPairs, slotMap);
if (dns.size() != 1) throw new IllegalArgumentException("parent key maps to " + dns.size() + " datanodes, need exactly 1");

Try / catch

try { insertChild(row); } catch (SQLNonTransientException e) { if (e.getMessage().contains("parent key can't find")) { /* insert parent first or fix key value */ } throw e; }

Prevention

When it happens

Trigger: INSERT into a child (ER) table where the parent key value, run through the parent table's rule algorithm, maps to no datanode or to multiple datanodes (e.g. parent uses a rule that fans out, or the join key value is out of the algorithm's range returning null/empty).

Common situations: Child table's <childTable> joinKey values not covered by the parent's sharding algorithm; parent table configured with a multi-node rule (e.g. a range rule matching multiple nodes); inserting child rows before any parent row exists.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/52aea27684d24a52. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/route/util/RouterUtil.java:1096

			RouteResultset rrs, TableConfig tc, String joinKeyVal)
			throws SQLNonTransientException {

		// only has one parent level and ER parent key is parent
		// table's partition key
		if (tc.isSecondLevel()
				//判断是否为二级子表(父表不再有父表)
				&& tc.getParentTC().getPartitionColumn()
				.equals(tc.getParentKey())) { // using
			// parent
			// rule to
			// find
			// datanode
			Set<ColumnRoutePair> parentColVal = new HashSet<ColumnRoutePair>(1);
			ColumnRoutePair pair = new ColumnRoutePair(joinKeyVal);
			parentColVal.add(pair);
			Set<String> dataNodeSet = ruleCalculate(tc.getParentTC(), parentColVal,rrs.getDataNodeSlotMap());
			if (dataNodeSet.isEmpty() || dataNodeSet.size() > 1) {
				throw new SQLNonTransientException(
						"parent key can't find  valid datanode ,expect 1 but found: "
								+ dataNodeSet.size());
			}
			String dn = dataNodeSet.iterator().next();
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("found partion node (using parent partion rule directly) for child table to insert  "
						+ dn + " sql :" + stmt);
			}
			return RouterUtil.routeToSingleNode(rrs, dn, stmt);
		}
		return null;
	}

	/**
	 * @return dataNodeIndex -&gt; [partitionKeysValueTuple+]
	 */
	public static Set<String> ruleByJoinValueCalculate(RouteResultset rrs, TableConfig tc,
			Set<ColumnRoutePair> colRoutePairSet) throws SQLNonTransientException {

View on GitHub (pinned to 65f8d8beb7)