{"record":{"id":"cddaaf3bbba74595","repo":"alibaba/spring-ai-alibaba","slug":"app-component-detail-error","errorCode":"APP_COMPONENT_DETAIL_ERROR","errorMessage":"Failed to query component detail.","messagePattern":"Failed to query component detail\\.","errorType":"error_code","errorClass":"BizException","httpStatus":500,"severity":"error","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/builder/controller/AppComponentController.java","lineNumber":286,"sourceCode":"\t\t\t\treturn Result.success(context.getRequestId(), null);\n\t\t\t}\n\t\t\t// get component inputScheme\n\t\t\tAppComponentConfig appComponentConfig = appComponentManager.getAppComponentInputConfig(appComponentByCode);\n\t\t\tString appId = appComponentByCode.getAppId();\n\t\t\tApplication application = appService.getApp(appId);\n\t\t\tif (application == null) {\n\t\t\t\treturn Result.error(context.getRequestId(), ErrorCode.APP_NOT_FOUND);\n\t\t\t}\n\t\t\t// get application inputScheme\n\t\t\tAppComponentConfig applicationInputConfig = appComponentManager.getApplicationInputConfig(application,\n\t\t\t\t\tfalse);\n\t\t\t// merge component config\n\t\t\tapplicationInputConfig = appComponentManager.mergeConfig(applicationInputConfig, appComponentConfig);\n\t\t\tappComponentByCode.setConfig(JsonUtils.toJson(applicationInputConfig));\n\t\t\treturn Result.success(context.getRequestId(), appComponentByCode);\n\t\t}\n\t\tcatch (Exception e) {\n\t\t\tthrow new BizException(ErrorCode.APP_COMPONENT_DETAIL_ERROR.toError());\n\t\t}\n\n\t}\n\n\t/**\n\t * Retrieves detailed information about a component by its application ID. Includes\n\t * merged configuration from both component and source application.\n\t * @param appId Application ID associated with the component\n\t * @return Result containing detailed AppComponent information with merged\n\t * configuration\n\t */\n\t@GetMapping(\"/{appId}/detail-by-appid\")\n\tpublic Result<AppComponent> detailByAppId(@PathVariable(\"appId\") String appId) {\n\t\tRequestContext context = RequestContextHolder.getRequestContext();\n\t\tif (StringUtils.isBlank(appId)) {\n\t\t\tthrow new BizException(ErrorCode.MISSING_PARAMS.toError(\"appId\"));\n\t\t}\n","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/builder/controller/AppComponentController.java#L268-L304","documentation":"BizException thrown by AppComponentController.detailByCode inside a catch-all when any step of fetching the published component, loading its source application config, or merging configurations throws. It intentionally obscures the root cause behind a generic 'failed to query component detail' message.","triggerScenarios":"GET /{code}/detail-by-code where getAppComponentByCode throws, the referenced source application cannot be loaded/parsed, appComponentManager.mergeConfig fails, or JsonUtils.toJson throws during the merge — any Exception in the try block.","commonSituations":"Malformed JSON stored in the app or component config column; source application deleted after component creation; merge logic hitting an unexpected config shape; DB errors during lookup.","solutions":["Temporarily log the caught exception (or inspect server logs) to identify which step failed — the BizException hides the cause.","Validate that the component's source application still exists and its config is valid JSON.","Check appComponentManager.mergeConfig inputs for null or incompatible config shapes.","Fix the corrupt/missing data, then retry the request."],"exampleFix":"// before\ncatch (Exception e) {\n    throw new BizException(ErrorCode.APP_COMPONENT_DETAIL_ERROR.toError());\n}\n// after\ncatch (Exception e) {\n    log.error(\"Failed to query component detail for code={}\", code, e);\n    throw new BizException(ErrorCode.APP_COMPONENT_DETAIL_ERROR.toError());\n}","handlingStrategy":"try-catch","validationCode":"const comp = await api.getComponentByCode(code);\nif (comp && comp.sourceAppId) await api.getApplication(comp.sourceAppId); // ensure source app exists and config parses\nJSON.parse(comp.config); // fail fast on corrupt config before merging","typeGuard":"function isValidComponentDetail(c) { return c != null && typeof c.code === 'string' && (!c.config || isPlainObject(safeParse(c.config))); }","tryCatchPattern":"try {\n  const detail = await api.getComponentDetail(code);\n} catch (e) {\n  if (e.code === 'APP_COMPONENT_DETAIL_ERROR') {\n    // inspect server logs for root cause: corrupt config JSON, missing source app, or merge failure\n  }\n}","preventionTips":["Validate config columns contain parseable JSON at write time.","Guarantee referential integrity between components and source apps.","Log the caught exception server-side so the generic message is diagnosable.","Add unit tests for mergeConfig with null and malformed configs."],"tags":["rest-api","config-merge","json","spring"],"backgroundTag":"api-error-response","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}