Troubleshoot editor
Before you start
The editor module provides headless editing primitives for attune-rag templates. It covers frontmatter parsing and schema validation (parse_frontmatter, validate_frontmatter, load_schema), lint diagnostics (lint_template), prefix-match autocomplete for tags and aliases, cross-corpus reference lookup (find_references), and rename refactoring (plan_rename, apply_rename). These are pure functions over a CorpusProtocol object. The same functions back both the attune-gui editor and the attune-author edit CLI.
Symptom table
| If you observe | Check |
|---|---|
SchemaError: Malformed YAML in frontmatter |
The raw YAML block passed to parse_frontmatter() — look for tabs, unquoted colons, or invalid Unicode |
validate_frontmatter() returns unexpected FrontmatterIssue entries |
Compare your frontmatter keys and types against the schema returned by load_schema() — FrontmatterIssue.path points to the offending key |
lint_template() returns no diagnostics when errors are expected |
Confirm you are passing the correct rel_path and a live corpus object — a mismatched path silently skips cross-template checks |
find_references() raises ValueError: Unsupported reference kind |
Verify the kind argument is a valid ReferenceKind enum member, not a raw string |
plan_rename() raises ValueError: Unsupported rename kind |
Same as above — check that kind is a ReferenceKind value |
apply_rename() raises RenameCollisionError |
The proposed new name already exists in the corpus; check RenameCollisionError.name and owning_path to identify the conflict |
apply_rename() raises RenameError: Corpus has no resolvable root path |
The corpus passed to apply_rename() does not expose a filesystem root — this operation requires a corpus backed by a real directory |
apply_rename() raises RenameError: File ... drifted from the planned base |
The file was modified on disk between calling plan_rename() and apply_rename() — rebuild the plan |
| Autocomplete returns an empty list | Confirm the prefix string matches the case used in the corpus and that limit is greater than zero |
Step-by-step diagnosis
Work from cheapest to most expensive.
-
Reproduce the failure in isolation. Call the failing function directly with the minimal required arguments. For example, to isolate a lint issue:
from attune_rag.editor.lint import lint_template diagnostics = lint_template(text="<your template>", rel_path="test.md", corpus=corpus) print([d.to_dict() for d in diagnostics])Confirm the failure occurs without any surrounding application code.
-
Inspect return values and raised exceptions. All public functions return typed results or raise documented exceptions. Check:
Diagnostic.severity,code,message,line, andcolfor lint failures.FrontmatterIssue.code,message, andpathfor schema violations.Reference.template_path,line, andcontextfor unexpected reference results.- The exception message text for
RenameErrorand its subclasses — each message names the specific file or value involved.
-
Validate your corpus object. Most functions accept
corpus: Anytyped againstCorpusProtocol. If results are silently wrong or empty, confirm the corpus is fully loaded and up to date. A stale or partially initialised corpus is a common source of empty autocomplete results and missing references. -
Check the
RenamePlanbefore applying it. Callplan_rename()and inspect the result withplan.to_dict()before passing it toapply_rename(). Verifyplan.editscontains the expectedFileEdithunks andplan.movescontains the expectedFileMoveentries. This lets you catch collision or path issues without touching the filesystem. -
Run the editor tests.
pytest -k "editor" -vIf a test covers the failing path, use its fixtures to reproduce the issue. A failing test here confirms a regression; a passing test with a failing manual call usually points to a corpus or input mismatch in your calling code.
Common fixes
-
Malformed frontmatter YAML. Fix tabs-instead-of-spaces, unquoted special characters, or duplicate keys in the frontmatter block, then re-run
parse_frontmatter(). TheSchemaErrormessage includes the YAML parser's description of the problem. -
Wrong
ReferenceKindvalue. Bothfind_references()andplan_rename()reject an unsupportedkindwith aValueError. Use the enum directly:from attune_rag.editor.references import ReferenceKind refs = find_references(corpus, name="my-alias", kind=ReferenceKind.ALIAS) -
Rename collision. If
apply_rename()raisesRenameCollisionError, either choose a different target name or remove/rename the existing item atowning_pathfirst. The error exposes bothnameandowning_pathfor inspection. -
Drifted file during rename. If you see
RenameError: File ... drifted from the planned base, the template was edited between planning and applying. Rebuild the plan:plan = plan_rename(corpus, old="old-name", new="new-name", kind=ReferenceKind.ALIAS) apply_rename(corpus, plan) -
Corpus has no root path.
apply_rename()requires a corpus with a resolvable filesystem root. If you are working with an in-memory corpus (for example, in tests), you cannot callapply_rename()— useplan_rename()to inspect the intended edits without applying them. -
Empty autocomplete results. If
autocomplete_tags()orautocomplete_aliases()return fewer results than expected, check thatprefixis correct (these are prefix matches, not substring matches) and that yourlimitargument is large enough. The defaultlimitis50.
Source files
src/attune_rag/editor/__init__.pysrc/attune_rag/editor/schema.pysrc/attune_rag/editor/lint.pysrc/attune_rag/editor/autocomplete.pysrc/attune_rag/editor/references.pysrc/attune_rag/editor/rename.py
Tags: editor, lint, rename, autocomplete, schema, references, refactor, template