{"record":{"id":"ef58ff0d6004c258","repo":"apache/incubator-seata","slug":"user-confirmation-string-is-required","errorCode":null,"errorMessage":"User confirmation string is required.","messagePattern":"User confirmation string is required\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"console/src/main/java/org/apache/seata/mcp/tools/ModifyConfirmTools.java","lineNumber":49,"sourceCode":"\n    private static final Logger LOGGER = LoggerFactory.getLogger(ModifyConfirmTools.class);\n\n    private final ModifyConfirmService modifyConfirmService;\n\n    public ModifyConfirmTools(ModifyConfirmService modifyConfirmService) {\n        this.modifyConfirmService = modifyConfirmService;\n    }\n\n    @McpTool(\n            description = \"Before modifying (update or delete) a transaction or lock, the user MUST manually confirm.\"\n                    + \"You are NOT allowed to fabricate or auto-confirm on behalf of the user.\")\n    public Map<String, String> confirmAndGetKey(\n            @McpToolParam(\n                            description =\n                                    \"The confirmation string provided by the USER (not generated by the LLM).The content must repeat the modification action clearly.\")\n                    String userInputStr) {\n        if (StringUtils.isBlank(userInputStr)) {\n            throw new IllegalArgumentException(\"User confirmation string is required.\");\n        }\n        if (!userInputStr.contains(\"确认\") && !userInputStr.contains(\"confirm\")) {\n            throw new IllegalArgumentException(\n                    \"Confirmation string must explicitly contain '确认' or 'confirm' and repeat the modification content. This must come from the user.\");\n        }\n        Map<String, String> keyMap = modifyConfirmService.confirmAndGetKey();\n        LOGGER.info(\"the user obtains a modify key:{}\", keyMap.get(\"modify_key\"));\n        return keyMap;\n    }\n}\n","sourceCodeStart":31,"sourceCodeEnd":60,"githubUrl":"https://github.com/apache/incubator-seata/blob/e01f97c6db397165050caa6764020410c2c8199a/console/src/main/java/org/apache/seata/mcp/tools/ModifyConfirmTools.java#L31-L60","documentation":"Thrown by the Seata MCP ModifyConfirmTools when the confirmAndGetKey tool is invoked with a null, empty, or whitespace-only userInputStr. This tool implements a human-in-the-loop gate: before any update/delete of a transaction or lock, the end user (not the LLM) must type a confirmation string, and the server issues a one-time modify key only after that.","triggerScenarios":"An MCP client or LLM calls the confirmAndGet_key tool without arguments, passes an empty string, or a calling agent omits the userInputStr parameter entirely.","commonSituations":"LLM agent tries to skip the confirmation step and call the modify tool directly; MCP client deserializes the argument to null; automated scripts call the tool non-interactively with no user present.","solutions":["Make the LLM/client always ask the real user for a typed confirmation before invoking the tool, and pass that exact text as userInputStr.","If building an MCP client, mark userInputStr as required so the schema rejects the call before it reaches the server.","If the workflow is fully automated, remove the modify-confirm gate from your deployment instead of bypassing it with blank input."],"exampleFix":"// before\nMap<String,String> key = tools.confirmAndGetKey(null);\n// after: collect the user's typed confirmation first\nMap<String,String> key = tools.confirmAndGetKey(\"confirm: delete xid 192.168.1.1:8091:123456\");","handlingStrategy":"validation","validationCode":"if (userInputStr == null || userInputStr.isBlank()) {\n    // ask the user; do NOT call the tool yet\n    return \"Confirmation required: please type your confirmation.\";\n}","typeGuard":"private boolean isConfirmable(String s) {\n    return s != null && !s.isBlank();\n}","tryCatchPattern":"catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"required\")) { promptUserForConfirmation(); }\n    else { throw e; }\n}","preventionTips":["Treat confirmAndGetKey input as user-originated only; never let the LLM fill it","Mark the MCP param required in client schemas","Log which user issued each modify key for audit"],"tags":["mcp","validation","human-in-the-loop","security"],"backgroundTag":null,"analyzedSha":"e01f97c6db397165050caa6764020410c2c8199a","analyzedAt":"2026-08-14T10:23:53.097Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}