{"record":{"id":"64183505dfcfbb5f","repo":"dromara/Sa-Token","slug":"10002","errorCode":"10002","errorMessage":"未能获取对应StpLogic，type=\" + loginType","messagePattern":"未能获取对应StpLogic，type=\" \\+ loginType","errorType":"exception","errorClass":"SaTokenException","httpStatus":null,"severity":"error","filePath":"sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java","lineNumber":356,"sourceCode":"\t\t\t// isCreate=true时，自创建模式：自动创建并返回 \n\t\t\tif(isCreate) {\n\t\t\t\tsynchronized (SaManager.class) {\n\t\t\t\t\tstpLogic = stpLogicMap.get(loginType);\n\t\t\t\t\tif(stpLogic == null) {\n\t\t\t\t\t\tstpLogic = SaStrategy.instance.createStpLogic.apply(loginType);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} \n\t\t\t// isCreate=false时，严格校验模式：抛出异常 \n\t\t\telse {\n\t\t\t\t/*\n\t\t\t\t * 此时有两种情况会造成 StpLogic == null \n\t\t\t\t * 1. loginType拼写错误，请改正 （建议使用常量） \n\t\t\t\t * 2. 自定义StpUtil尚未初始化（静态类中的属性至少一次调用后才会初始化），解决方法两种\n\t\t\t\t * \t\t(1) 从main方法里调用一次\n\t\t\t\t * \t\t(2) 在自定义StpUtil类加上类似 @Component 的注解让容器启动时扫描到自动初始化 \n\t\t\t\t */\n\t\t\t\tthrow new SaTokenException(\"未能获取对应StpLogic，type=\"+ loginType).setCode(SaErrorCode.CODE_10002);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// 返回 \n\t\treturn stpLogic;\n\t}\n\t\n}\n","sourceCodeStart":338,"sourceCodeEnd":365,"githubUrl":"https://github.com/dromara/Sa-Token/blob/ac2c7f6e94a78573cf0bcb932dd8b04e68fad189/sa-token-core/src/main/java/cn/dev33/satoken/SaManager.java#L338-L365","documentation":"Thrown by Sa-Token's JFinal plugin (SaTokenActionHandler) when a controller finishes with a ForwardActionRender whose target action URL is identical to the URL currently being handled. The handler would recursively call handle(actionUrl, ...) forever, so it detects self-forwarding and fails fast instead of overflowing the stack.","triggerScenarios":"A JFinal controller executes render(...) with a ForwardActionRender (e.g. controller.forwardAction or an interceptor that forwards) where getActionUrl() returns exactly the same target string the handler is already processing; typically the result of string concatenation or a config value that points the route back at itself.","commonSituations":"Route config points a path to a controller that forwards back to the same path; a default-route fallback forwards '/' to a URL that is itself '/'; typos in a forward target that happen to equal the current URL; refactoring that left a self-referencing forward.","solutions":["Find the ForwardActionRender being created (controller action or interceptor) and make its action URL different from the incoming target","If the forward target is configurable, fix the route/config value so it does not resolve to the same action","Guard before forwarding: if (actionUrl.equals(target)) return a 404/error render instead of forwarding","Add a unit test asserting the forward target never equals the original route for your default/error paths"],"exampleFix":"// before\npublic void index() {\n    render(new ForwardActionRender(getPara(\"to\"))); // ?to=/index -> self-forward\n}\n\n// after\npublic void index() {\n    String to = getPara(\"to\");\n    if (to == null || to.equals(\"/index\")) {\n        renderError(404);\n        return;\n    }\n    render(new ForwardActionRender(to));\n}","handlingStrategy":"validation","validationCode":"String target = request.getRequestURI();\nString actionUrl = forwardRender.getActionUrl();\nif (target.equals(actionUrl)) {\n    // refuse to self-forward; render an error instead\n    controller.renderError(404);\n    return;\n}\nhandle(actionUrl, request, response, isHandled);","typeGuard":null,"tryCatchPattern":"catch (RuntimeException e) when message contains 'forward action url is the same as before': log target + actionUrl, render 404/500 once, do NOT re-invoke the forward","preventionTips":["Never derive a forward target from unvalidated request input","Keep a routing table test asserting every configured forward target differs from its source path","Centralize forwards in one helper that rejects target.equals(source)"],"tags":["jfinal","routing","infinite-loop","forward","sa-token"],"backgroundTag":null,"analyzedSha":"ac2c7f6e94a78573cf0bcb932dd8b04e68fad189","analyzedAt":"2026-08-14T14:36:10.271Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}