{"record":{"id":"a21abfb516ae64a2","repo":"MyCATApache/Mycat-Server","slug":"er-user-read-only","errorCode":"ER_USER_READ_ONLY","errorMessage":"User readonly","messagePattern":"User readonly","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/server/ServerQueryHandler.java","lineNumber":165,"sourceCode":"\t\t        e.printStackTrace();\n                String msg = \"Mycat is not connected to zookeeper!!\\n\";\n                msg += \"Please start zookeeper and restart mycat so that this mycat can temporarily execute the migration command.If other mycat does not connect to this zookeeper, they will not be able to perceive changes in the migration task.\\n\";\n                msg += \"After starting zookeeper,you can command tas follow:\\n\\nmigrate -table=schema.test -add=dn2,dn3 -force=true\\n\\nto perform the migration.\\n\";\n                LOGGER.error(e.getMessage());\n                LOGGER.error(msg);\n                c.writeErrMessage(ErrorCode.ER_UNKNOWN_ERROR, msg);\n            }\n\t\t\tbreak;\n\t\t}\n\t\tcase ServerParse.LOCK:\n        \tc.lockTable(sql);\n        \tbreak;\n        case ServerParse.UNLOCK:\n        \tc.unLockTable(sql);\n        \tbreak;\n\t\tdefault:\n\t\t\tif(readOnly){\n\t\t\t\tLOGGER.warn(new StringBuilder().append(\"User readonly:\").append(sql).toString());\n\t\t\t\tc.writeErrMessage(ErrorCode.ER_USER_READ_ONLY, \"User readonly\");\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tc.execute(sql, rs & 0xff);\n\t\t}\n\n\t\tswitch (sqlType) {\n\t\t\tcase ServerParse.SELECT:\n\t\t\tcase ServerParse.DELETE:\n\t\t\tcase ServerParse.UPDATE:\n\t\t\tcase ServerParse.INSERT:\n\t\t\tcase ServerParse.COMMAND:\n\t\t\t\t// curd 在后面会更新\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tc.setExecuteSql(null);\n\t\t}\n\t}","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/server/ServerQueryHandler.java#L147-L183","documentation":"When a statement falls into the default case of ServerQueryHandler.query (i.e. a write or otherwise non-handled statement type) and the current user is configured as read-only (readOnly flag on the front-end connection), MyCat rejects it with ER_USER_READ_ONLY and message 'User readonly'.","triggerScenarios":"A user marked read-only (readOnly=true in server.xml user config) issues INSERT/UPDATE/DELETE/DDL or any statement reaching the default branch.","commonSituations":"Reporting/analytics user accidentally used for writes; app deployed with wrong credentials; DDL migrations run under a read-only account.","solutions":["Use a non-read-only MyCat user for write operations.","If writes are legitimate, set readOnly=false (or remove readOnly) for that user in server.xml and reconnect.","Check application connection config points at the correct user profile."],"exampleFix":"// before (server.xml)\n<user name=\"app\"><property name=\"readOnly\">true</property>...</user>\n// after\n<user name=\"app\"><property name=\"readOnly\">false</property>...</user>","handlingStrategy":"validation","validationCode":"// Check statement type against user's read-only profile before executing\nboolean isWrite = matchesAny(sql, \"INSERT\", \"UPDATE\", \"DELETE\", \"CREATE\", \"DROP\", \"ALTER\", \"TRUNCATE\");\nif (isWrite && currentUserReadOnly) {\n    throw new SecurityException(\"user is read-only; refuse write: \" + sql);\n}","typeGuard":null,"tryCatchPattern":"try {\n    stmt.execute(sql);\n} catch (SQLException e) {\n    if (e.getErrorCode() == 1820 /* ER_USER_READ_ONLY */) {\n        throw new SecurityException(\"Switch to a writable MyCat user for this operation\", e);\n    }\n    throw e;\n}","preventionTips":["Separate read-only and write connection pools per user","Review server.xml readOnly flags in deployment checklists","Run migrations with an account that has write privileges"],"tags":["permissions","readonly","user-config","security"],"backgroundTag":"permission-denied","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}