Related to #5, but worth fixing independently of the reconnect work.
Problem
QueryTool::mapThrowableToToolUsageError() maps every DbalException to the same generic error:
if ($error instanceof DbalException) {
return new ToolUsageError(
message: $error->getMessage(),
hint: 'Query failed in the database. Verify table/column names and SQL syntax, then retry.',
retryable: true,
);
}
When the underlying failure is a dead connection (SSL SYSCALL error: EOF detected, no connection to the server), this hint is actively misleading: it tells the LLM client the SQL is wrong and that retrying helps. Observed behaviour in practice: the model re-checks its query syntax, retries the identical (correct) SQL, gets the identical error, and burns several round-trips before concluding the connection is dead. retryable: true on a permanently-dead handle makes it worse.
Suggestion
In the error mapper, branch on connection-level failures before the generic DbalException case — DBAL 4 already gives you Doctrine\DBAL\Exception\ConnectionLost / ConnectionException for most of these, plus a message match for the driver-level stragglers (SSL SYSCALL, EOF detected, no connection to the server, server has gone away, Communication link failure):
if ($error instanceof ConnectionLost || $this->isBrokenConnection($error)) {
return new ToolUsageError(
message: $error->getMessage(),
hint: 'Database connection was lost. Do not modify the query — the SQL is not the problem. Ask the user to restart/reconnect the MCP server.',
retryable: false, // flip to true once auto-reconnect (#5) exists
);
}
Once #5's close-and-retry lands, this branch becomes the fallback for "reconnect attempted and still failed", and the hint can say that instead.
Same applies to SchemaTool's error mapping.
Related to #5, but worth fixing independently of the reconnect work.
Problem
QueryTool::mapThrowableToToolUsageError()maps everyDbalExceptionto the same generic error:When the underlying failure is a dead connection (
SSL SYSCALL error: EOF detected,no connection to the server), this hint is actively misleading: it tells the LLM client the SQL is wrong and that retrying helps. Observed behaviour in practice: the model re-checks its query syntax, retries the identical (correct) SQL, gets the identical error, and burns several round-trips before concluding the connection is dead.retryable: trueon a permanently-dead handle makes it worse.Suggestion
In the error mapper, branch on connection-level failures before the generic
DbalExceptioncase — DBAL 4 already gives youDoctrine\DBAL\Exception\ConnectionLost/ConnectionExceptionfor most of these, plus a message match for the driver-level stragglers (SSL SYSCALL,EOF detected,no connection to the server,server has gone away,Communication link failure):Once #5's close-and-retry lands, this branch becomes the fallback for "reconnect attempted and still failed", and the hint can say that instead.
Same applies to
SchemaTool's error mapping.