{"record":{"id":"a3d9faa777f3f23a","repo":"infiniflow/ragflow","slug":"template-child-id-does-not-belong-to-this-group","errorCode":null,"errorMessage":"Template {child_id} does not belong to this group.","messagePattern":"Template (.+?) does not belong to this group\\.","errorType":"validation","errorClass":"GroupValidationError","httpStatus":null,"severity":"error","filePath":"api/db/services/compilation_template_group_service.py","lineNumber":315,"sourceCode":"\n            if templates is not None:\n                current_children = list(\n                    CompilationTemplate.select()\n                    .where(\n                        CompilationTemplate.group_id == group_id,\n                        CompilationTemplate.status == StatusEnum.VALID.value,\n                    )\n                    .order_by(CompilationTemplate.create_time.asc())\n                )\n                current_by_id = {child.id: child for child in current_children}\n                retained_ids: set[str] = set()\n                seen_names: set[str] = set()\n\n                for index, child in enumerate(templates):\n                    child_id = str((child or {}).get(\"id\") or \"\").strip()\n                    target = current_by_id.get(child_id) if child_id else None\n                    if child_id and target is None:\n                        raise GroupValidationError(f\"Template {child_id} does not belong to this group.\")\n                    # Older clients did not send child ids. Preserve their\n                    # existing ids by matching the submitted order.\n                    if target is None and not child_id and index < len(current_children):\n                        target = current_children[index]\n\n                    kind = str((child or {}).get(\"kind\") or \"\").strip()\n                    name = str((child or {}).get(\"name\") or \"\").strip()\n                    config = (child or {}).get(\"config\") or {}\n                    if not kind or not name or not isinstance(config, dict):\n                        raise GroupValidationError(\"Each template must include a name, kind, and config object.\")\n                    if name in seen_names:\n                        raise GroupValidationError(f\"Template name '{name}' is duplicated in this group.\")\n                    seen_names.add(name)\n\n                    from api.db.services.compilation_template_service import CompilationTemplateService\n\n                    config = CompilationTemplateService.fill_config_default_llm(config, tenant_id)\n                    duplicate_query = CompilationTemplate.select().where(","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/db/services/compilation_template_group_service.py#L297-L333","documentation":"Raised while updating a compilation template group when a submitted child template carries an id that does not match any existing VALID template row in that group (current_by_id lookup fails). It is a referential-integrity guard: child ids must reference templates already belonging to the same group_id and tenant.","triggerScenarios":"Group update API call where a template entry includes a non-empty id that is not among the group's current VALID children — e.g. an id from another group, a deleted/soft-deleted template, or a stale id from before the group was recreated.","commonSituations":"Editing a group in one browser tab after the template was removed or moved in another; frontend caching old template ids after a group restructure; copying group JSON between environments where ids differ.","solutions":["Refetch the group and its templates to get current ids before submitting the update.","If adding a brand-new template, omit the id field entirely — the server assigns one (or falls back to positional matching for legacy clients without ids).","If the template was deleted, re-create it instead of submitting its old id."],"exampleFix":"// before\n{\"id\": \"stale-or-foreign-template-id\", \"name\": \"T\", \"kind\": \"tree\", \"config\": {}}\n// after (new template: no id)\n{\"name\": \"T\", \"kind\": \"tree\", \"config\": {}}","handlingStrategy":"validation","validationCode":"current = {t.id for t in fetch_group_templates(group_id)}\nfor t in payload['templates']:\n    tid = str(t.get('id') or '').strip()\n    if tid and tid not in current:\n        raise ValueError(f'stale child id {tid}; refetch group')","typeGuard":null,"tryCatchPattern":"try:\n    save_group(group_id, payload)\nexcept GroupValidationError as e:\n    if 'does not belong to this group' in str(e):\n        payload = refresh_ids_and_retry(group_id, payload)  # refetch then resubmit\n    else:\n        raise","preventionTips":["Always GET the group immediately before PUT to refresh child ids.","Omit id for brand-new templates; never fabricate ids client-side."],"tags":["validation","compilation-template","stale-id","group-update"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}