{"record":{"id":"2905c1c4566e40eb","repo":"apache/shardingsphere","slug":"s-execution-mode-must-be-one-of-s","errorCode":null,"errorMessage":"%s execution_mode must be one of %s.","messagePattern":"(.+?) execution_mode must be one of (.+?)\\.","errorType":"validation","errorClass":"MCPInvalidExecutionModeException","httpStatus":null,"severity":"error","filePath":"mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExecuteUpdateToolHandler.java","lineNumber":105,"sourceCode":"    private ClassificationResult checkUpdateStatement(final MCPFeatureRequestContext requestContext, final MCPToolArguments toolArguments, final String sql) {\n        ClassificationResult classificationResult = SQLExecutionToolHandlerSupport.analyze(requestContext, toolArguments, sql);\n        if (SQLExecutionToolHandlerSupport.isQueryStatement(classificationResult)) {\n            throw new SQLToolMismatchException(\"database_gateway_execute_update does not accept read-only SQL. Use database_gateway_execute_query for read-only SQL.\",\n                    CoreToolNames.EXECUTE_UPDATE, CoreToolNames.EXECUTE_QUERY, classificationResult,\n                    createQuerySuggestedArguments(toolArguments, classificationResult));\n        }\n        return classificationResult;\n    }\n    \n    private String resolveExecutionMode(final MCPToolArguments toolArguments) {\n        String result = toolArguments.getStringArgument(MCPPayloadFieldNames.EXECUTION_MODE);\n        if (result.isEmpty()) {\n            throw new MCPExecutionModeRequiredException(CoreToolNames.EXECUTE_UPDATE, EXECUTION_MODES, createPreviewSuggestedArguments(toolArguments));\n        }\n        if (EXECUTION_MODE_EXECUTE.equals(result) || EXECUTION_MODE_PREVIEW.equals(result)) {\n            return result;\n        }\n        throw new MCPInvalidExecutionModeException(CoreToolNames.EXECUTE_UPDATE, EXECUTION_MODES, createPreviewSuggestedArguments(toolArguments));\n    }\n    \n    private MCPSuccessPayload createPreviewResponse(final MCPToolArguments toolArguments, final ClassificationResult classificationResult) {\n        Map<String, Object> result = new LinkedHashMap<>(17, 1F);\n        result.put(\"response_mode\", MCPResponseMode.PREVIEW);\n        result.put(\"result_kind\", RESULT_KIND_PREVIEW);\n        result.put(MCPPayloadFieldNames.EXECUTION_MODE, EXECUTION_MODE_PREVIEW);\n        result.put(\"preview_semantics\", \"classification_only\");\n        result.put(\"affected_rows_estimated\", false);\n        result.put(\"status\", \"PREVIEWED\");\n        result.put(\"would_execute\", false);\n        result.put(\"statement_class\", classificationResult.getStatementClass().name().toLowerCase(Locale.ENGLISH));\n        result.put(\"statement_type\", classificationResult.getStatementType());\n        result.put(\"normalized_sql\", classificationResult.getNormalizedSql());\n        result.put(\"side_effect_scope\", createSideEffectScope(classificationResult));\n        classificationResult.getTargetObjectName().ifPresent(optional -> result.put(\"target_object\", optional));\n        classificationResult.getSavepointName().ifPresent(optional -> result.put(\"savepoint\", optional));\n        result.put(\"review_guidance\", createReviewGuidance(classificationResult));","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExecuteUpdateToolHandler.java#L87-L123","documentation":"After confirming execution_mode is present, resolveExecutionMode accepts only the exact values 'execute' or 'preview'; anything else throws MCPInvalidExecutionModeException ('%s execution_mode must be one of %s.'). The strict whitelist prevents accidental mutations via fuzzy values like 'run', 'dry-run', or differently-cased strings. Suggested arguments for a preview retry are attached to the exception.","triggerScenarios":"Passing execution_mode values such as 'EXECUTE' (wrong case), 'run', 'dry_run', 'dry-run', 'apply', or trailing whitespace — anything not exactly 'execute' or 'preview'.","commonSituations":"LLM paraphrasing the mode; enum mapping from a client that uses different names ('dry-run' for preview); case-sensitivity surprises; whitespace from templated payloads.","solutions":["Use exactly 'execute' or 'preview' (lowercase, no whitespace).","Map client-side enums: dryRun->'preview', everything-else->'execute' explicitly.","Trim and lowercase execution_mode before sending."],"exampleFix":"// before\nawait tools.call('database_gateway_execute_update', { sql, execution_mode: 'dry-run' }); // must be one of [execute, preview]\n\n// after\nconst mode = opts.dryRun ? 'preview' : 'execute';\nawait tools.call('database_gateway_execute_update', { sql, execution_mode: mode });","handlingStrategy":"validation","validationCode":"const EXECUTION_MODES = new Set(['execute', 'preview']);\nfunction normalizeMode(raw) {\n  const mode = String(raw ?? '').trim().toLowerCase();\n  if (!EXECUTION_MODES.has(mode)) throw new Error(`execution_mode must be one of [execute, preview], got '${raw}'`);\n  return mode;\n}\nconst args = { sql, execution_mode: normalizeMode(userChoice) };","typeGuard":"function isExecutionMode(value) {\n  return value === 'execute' || value === 'preview';\n}","tryCatchPattern":"try {\n  return await tools.call('database_gateway_execute_update', args);\n} catch (e) {\n  if (/execution_mode must be one of/.test(e.message)) {\n    return tools.call('database_gateway_execute_update', { ...args, execution_mode: args.dryRun ? 'preview' : 'execute' });\n  }\n  throw e;\n}","preventionTips":["Whitelist and normalize execution_mode to exact lowercase 'execute'/'preview'.","Map your client's enum (dryRun etc.) to the two contract values before sending.","Trim whitespace; the comparison is exact."],"tags":["mcp","tool-arguments","validation","execution-mode","enum"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}