{"record":{"id":"07c6a6f5100bbff6","repo":"OtterMind/Chat2DB","slug":"routine-operation-parameterloadfailed","errorCode":"routine.operation.parameterLoadFailed","errorMessage":"routine.operation.parameterLoadFailed","messagePattern":"routine\\.operation\\.parameterLoadFailed","errorType":"exception","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-plugins/chat2db-community-mysql/src/main/java/ai/chat2db/plugin/mysql/MysqlRoutineManager.java","lineNumber":321,"sourceCode":"            if (FUNCTION.equals(routineType)) {\n                return metaData.getFunctionParameters(connection, databaseName, StringUtils.trimToNull(operation.getSchemaName()),\n                                routineName)\n                        .stream()\n                        .map(mysqlRoutineConverter::functionParameter2routineParameter)\n                        .filter(Objects::nonNull)\n                        .sorted((left, right) -> Integer.compare(left.ordinalPosition(), right.ordinalPosition()))\n                        .toList();\n            }\n\n            return metaData.getProcedureParameters(connection, databaseName, StringUtils.trimToNull(operation.getSchemaName()),\n                            routineName)\n                    .stream()\n                    .map(mysqlRoutineConverter::procedureParameter2routineParameter)\n                    .filter(Objects::nonNull)\n                    .sorted((left, right) -> Integer.compare(left.ordinalPosition(), right.ordinalPosition()))\n                    .toList();\n        } catch (Exception e) {\n            throw new BusinessException(\"routine.operation.parameterLoadFailed\", new Object[]{e.getMessage()}, e);\n        }\n    }\n\n    private String normalizeRoutineType(String routineType) {\n        String normalized = StringUtils.trimToEmpty(routineType).toUpperCase(Locale.ROOT);\n        if (!FUNCTION.equals(normalized) && !PROCEDURE.equals(normalized)) {\n            throw new BusinessException(\"routine.operation.typeUnsupported\");\n        }\n        return normalized;\n    }\n\n    private String requireRoutineName(RoutineOperation operation) {\n        String routineName = StringUtils.trimToEmpty(operation.getRoutineName());\n        if (StringUtils.isBlank(routineName)) {\n            throw new BusinessException(\"routine.operation.nameRequired\");\n        }\n        return routineName;\n    }","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-plugins/chat2db-community-mysql/src/main/java/ai/chat2db/plugin/mysql/MysqlRoutineManager.java#L303-L339","documentation":"Thrown by queryRoutineParameters when loading a routine's parameter metadata fails for any reason. The original exception is wrapped in BusinessException('routine.operation.parameterLoadFailed', {causeMessage}) so the caller gets a localized message while the root SQLException is preserved as the cause. It fires during previewInvocation when building the parameter list.","triggerScenarios":"previewInvocation → queryRoutineParameters calls metaData.getFunctionParameters/getProcedureParameters, which throws. Typical causes: the connected user lacks SELECT on mysql.proc / information_schema, the routine name does not resolve, the connection is closed, or the JDBC driver cannot parse the parameter metadata.","commonSituations":"Invoking (previewing) a procedure/function with a low-privilege connection; referencing a routine that was renamed or dropped; a network blip dropping the connection mid-query; an older MySQL Connector/J that returns incomplete routine metadata.","solutions":["Grant the invoking user SELECT privilege on the routine metadata (information_schema / mysql.proc) or the routine itself.","Verify the routine name and database in the operation match an existing routine before previewing.","Inspect BusinessException.getCause() for the underlying SQLException to get the SQL state and vendor error code.","Ensure the connection is still open and not shared across threads during the metadata call."],"exampleFix":"// before\nroutineManager.previewInvocation(connection, operation);\n\n// after\ntry {\n    SqlPreview preview = routineManager.previewInvocation(connection, operation);\n} catch (BusinessException e) {\n    if (\"routine.operation.parameterLoadFailed\".equals(e.getCode())) {\n        Throwable cause = e.getCause();\n        log.warn(\"Cannot load params for {}: {}\", operation.getRoutineName(),\n            cause == null ? e.getMessage() : cause.getMessage());\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"// Ensure the routine exists and the user has metadata privileges before previewing.\nif (!routineExistsByName(connection, db, name, type)) {\n    throw new IllegalArgumentException(\"routine not found\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    routineManager.previewInvocation(connection, operation);\n} catch (BusinessException e) {\n    if (\"routine.operation.parameterLoadFailed\".equals(e.getCode())) {\n        Throwable cause = e.getCause();\n        log.warn(\"param load failed: {}\", cause == null ? e.getMessage() : cause.getMessage());\n    }\n    throw e;\n}","preventionTips":["Grant metadata read privileges to the invoking account.","Verify the routine exists by name before previewing.","Do not share a single connection across threads during metadata calls.","Inspect the wrapped cause for the SQL state to diagnose denial vs. missing routine."],"tags":["mysql","routine","metadata","privilege"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}