{"record":{"id":"f6e1d833783bbfa0","repo":"iflytek/astron-agent","slug":"repo-knowledge-no-task","errorCode":"REPO_KNOWLEDGE_NO_TASK","errorMessage":"ResponseEnum.REPO_KNOWLEDGE_NO_TASK","messagePattern":"ResponseEnum\\.REPO_KNOWLEDGE_NO_TASK","errorType":"error_code","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/KnowledgeService.java","lineNumber":1330,"sourceCode":"        // }\n    }\n\n\n    /**\n     * Handle callback result for knowledge extraction task with retry mechanism\n     *\n     * @param retResult JSON object containing the callback result with task status and data\n     * @throws BusinessException if task not found or processing fails\n     */\n    @Retryable(value = Exception.class, backoff = @Backoff(delay = 5000, multiplier = 1, maxDelay = 10000))\n    public void dealTaskForKnowledgeExtract(JSONObject retResult) {\n        log.info(\"dealTaskForKnowledgeExtract callback result:{}\", JSONObject.toJSONString(retResult));\n        // 1. Query task\n        String taskId = retResult.getString(\"taskId\");\n        ExtractKnowledgeTask extractKnowledgeTask = extractKnowledgeTaskService.getOnly(Wrappers.lambdaQuery(ExtractKnowledgeTask.class).eq(ExtractKnowledgeTask::getTaskId, taskId));\n        if (extractKnowledgeTask == null || extractKnowledgeTask.getStatus() != 0) {\n            log.error(\"No corresponding task found: \" + taskId);\n            throw new BusinessException(ResponseEnum.REPO_KNOWLEDGE_NO_TASK);\n        }\n\n        boolean success = retResult.getBooleanValue(\"success\");\n        // If successful, parse knowledge points and store in database\n        String resultTextUrl = retResult.getString(\"knowledgeUrl\");\n        this.downloadKnowLedgeData(resultTextUrl, extractKnowledgeTask, success, retResult.getString(\"err\"));\n    }\n\n\n    /**\n     * Download and process knowledge data from a given URL\n     *\n     * @param url the URL to download knowledge data from\n     * @param extractKnowledgeTask the extraction task object to be updated\n     * @param isSuccess boolean flag indicating if the extraction was successful\n     * @param errMsg error message if extraction failed, null if successful\n     * @throws BusinessException if file not found, download fails, or data processing fails\n     */","sourceCodeStart":1312,"sourceCodeEnd":1348,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/console/backend/toolkit/src/main/java/com/iflytek/astron/console/toolkit/service/repo/KnowledgeService.java#L1312-L1348","documentation":"BusinessException REPO_KNOWLEDGE_NO_TASK thrown by dealTaskForKnowledgeExtract when the callback's taskId has no matching ExtractKnowledgeTask row, or the matching task's status is not 0 (pending). The method is @Retryable, so a BusinessException here is retried (5s backoff) — but for a genuinely unknown/completed task the retry only repeats the failure. It guards against processing callbacks for tasks that don't exist or were already handled.","triggerScenarios":"Knowledge-extraction callback arrives with a taskId that: was never created in this environment (misrouted callback), references a task already processed (status != 0, duplicate callback delivery), or references a task row deleted/purged before the callback arrived.","commonSituations":"Callback URL configured to point at the wrong environment (staging callback hitting prod). Message-queue redelivery or upstream retrying a callback after success. Task rows cleaned by a retention job while the external extractor still runs. Clock/latency causing duplicate callback processing.","solutions":["Check task existence and status: SELECT * FROM extract_knowledge_task WHERE task_id = '<taskId>'.","If status != 0 the task was already processed — treat the callback as a duplicate and have the caller stop retrying (the @Retryable will re-fail otherwise).","Fix callback routing so each environment receives only its own taskIds.","If the task should exist, verify it wasn't purged by retention jobs and re-submit the extraction job."],"exampleFix":"// before\nif (extractKnowledgeTask == null || extractKnowledgeTask.getStatus() != 0) {\n    throw new BusinessException(ResponseEnum.REPO_KNOWLEDGE_NO_TASK); // retried 5x even for duplicates\n}\n// after (idempotent no-op for duplicates)\nif (extractKnowledgeTask == null) { throw new BusinessException(ResponseEnum.REPO_KNOWLEDGE_NO_TASK); }\nif (extractKnowledgeTask.getStatus() != 0) {\n    log.info(\"task {} already processed (status={}), ignoring duplicate callback\", taskId, extractKnowledgeTask.getStatus());\n    return;\n}","handlingStrategy":"validation","validationCode":"ExtractKnowledgeTask t = extractKnowledgeTaskService.getOne(\n    new LambdaQueryWrapper<ExtractKnowledgeTask>().eq(ExtractKnowledgeTask::getTaskId, taskId));\nif (t == null || t.getStatus() != 0) { ignoreCallback(taskId); return; }","typeGuard":null,"tryCatchPattern":"try { dealTaskForKnowledgeExtract(result); } catch (BusinessException e) { if (\"REPO_KNOWLEDGE_NO_TASK\".equals(e.getCode())) { log.info(\"unknown/duplicate task callback {}\", result.getString(\"taskId\")); } else { throw e; } }","preventionTips":["Make callbacks idempotent: check status before processing and no-op on duplicates.","Verify callback URLs per environment in extractor configuration.","Keep extract_knowledge_task retention longer than the upstream extractor's maximum runtime."],"tags":["async-callback","task-processing","duplicate-delivery","java"],"backgroundTag":"record-not-found","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}