Skip to content

Misleading error hint + retryable:true on dead-connection errors (points LLM at SQL syntax instead of the connection) #7

Description

@ineersa

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions