{"record":{"id":"41695c5b5012c6c3","repo":"alibaba/spring-ai-alibaba","slug":"id-41695c","errorCode":null,"errorMessage":"未找到ID为{}的实验","messagePattern":"未找到ID为(.+?)的实验","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/service/impl/ExperimentServiceImpl.java","lineNumber":142,"sourceCode":"                (long) request.getPageNumber(),\n                (long) request.getPageSize(),\n                experimentDOList.stream()\n                        .map(Experiment::fromDO)\n                        .toList());\n\n    }\n\n    @Override\n    public Experiment getById(Long id) {\n        log.info(\"查询实验详情: {}\", id);\n        \n        if (id == null) {\n            throw new IllegalArgumentException(\"Experiment ID cannot be null\");\n        }\n        \n        ExperimentDO experimentDO = experimentMapper.selectById(id);\n        if (experimentDO == null) {\n            log.warn(\"未找到ID为{}的实验\", id);\n            return null;\n        }\n\n        Experiment experiment = Experiment.fromDO(experimentDO);\n\n        List<EvaluatorConfig> evaluatorConfigList = JSON.parseArray(experiment.getEvaluatorConfig(), EvaluatorConfig.class);\n\n        evaluatorConfigList.stream()\n                .filter(Objects::nonNull)\n                .forEach(evaluatorConfig -> {\n                    try {\n                        EvaluatorDO evaluatorDO = evaluatorMapper.selectById(evaluatorConfig.getEvaluatorId());\n                        evaluatorConfig.setEvaluatorName(evaluatorDO != null ? evaluatorDO.getName() : \"Unknown Evaluator\");\n                    } catch (Exception e) {\n                        log.warn(\"Failed to fetch evaluator name for id: {}\", evaluatorConfig.getEvaluatorId(), e);\n                        evaluatorConfig.setEvaluatorName(\"Error Fetching Name\");\n                    }\n                });","sourceCodeStart":124,"sourceCodeEnd":160,"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/service/impl/ExperimentServiceImpl.java#L124-L160","documentation":"ExperimentServiceImpl.getById logs this warning when experimentMapper.selectById(id) returns null, meaning no experiment row exists for the given ID. The method then returns null; it does not throw. Callers that skip the null check will hit a NullPointerException when using the returned Experiment.","triggerScenarios":"Calling experimentService.getById(id) with an ID absent from the experiment table, e.g., a deleted experiment or an ID from another environment/database.","commonSituations":"UI retains a link to a removed experiment; concurrent deletion between listing and detail fetch; tests use arbitrary IDs without seeding; wrong datasource pointing at an empty schema.","solutions":["Check experiment existence (experimentMapper.selectById or a COUNT query) before calling getById.","Null-check the return value and map it to a NOT_FOUND response.","Confirm the application is connected to the intended database/environment.","Re-create the experiment if it was deleted, or refresh the ID from a fresh list() call."],"exampleFix":"// before\nExperiment exp = experimentService.getById(id);\nLong versionId = exp.getDatasetVersionId(); // NPE if not found\n\n// after\nExperiment exp = experimentService.getById(id);\nif (exp == null) {\n    throw new ResponseStatusException(HttpStatus.NOT_FOUND, \"Experiment not found: \" + id);\n}","handlingStrategy":"type-guard","validationCode":"public static boolean experimentExists(Long id) {\n    return id != null && experimentMapper.selectById(id) != null;\n}","typeGuard":"Experiment exp = experimentService.getById(id);\nif (exp == null) {\n    throw new ResponseStatusException(HttpStatus.NOT_FOUND, \"Experiment not found: \" + id);\n}","tryCatchPattern":null,"preventionTips":["Null-check results from experimentService.getById before dereferencing.","Refresh experiment IDs from list() rather than caching them across sessions.","Confirm the datasource points at the expected environment.","Handle deletion races: re-fetch on 404 in UI flows."],"tags":["java","spring","mybatis","experiment","null-return"],"backgroundTag":"resource-not-found","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}