Troubleshooting and stable errors
Catch KenkuiError subclasses and branch on error.code, not message text.
ErrorCode values are machine-readable and messages are sanitized; paths,
provider exceptions, and subprocess output are intentionally not public.
import kenkui as kk
try:
kk.epub("book.epub").assign_voice("voice").tts().inspect()
except kk.KenkuiError as error:
print(error.code.value, str(error))
Python or locked environment
Use CPython 3.11, 3.12, or 3.13. Other versions are outside the declared range. For contributors, verify rather than update the committed lock:
uv lock --check
uv sync --frozen --all-groups
Run repository commands through uv run, or install the built wheel into the
active environment.
Source and EPUB failures
unsupported_format: use an.epubpath.source_not_found/source_not_readable: check the path, regular-file state, and current-user read permission.malformed_epub: ZIP/package/XHTML structure is invalid or unsupported.unsafe_archive_path: a member path is unsafe; do not extract or rewrite an untrusted archive to bypass this check.archive_limit: a fixed ZIP/XML/spine/text safety budget was exceeded.empty_chapter,chapter_not_found,reversed_chapter_range: inspect chapter IDs and visible text before selecting.empty_chaptermeans the whole book yielded no visible text; individual text-free spine items, such as image-only covers and title pages, are skipped and never appear in inspection.
See security boundaries for exact limits.
Character analysis and checkpoints
spacy_package_missing/spacy_pipeline_missing: install the optional dependency and the selected language pipeline in the active environment; see spaCy setup.invalid_model: supply a nonempty model identifier. Local roster discovery accepts"spacy"or"spacy:<installed_pipeline>"; attribution needs a configured LiteLLM model.invalid_roster: correct duplicate/reserved IDs, invalid fields, chapter IDs, or a narrator reference that is absent from the roster. See character review.invalid_resolution_stage: useuntil="characters"oruntil="casting".source_changed: the EPUB differs from the checkpoint. Resolve it again; for a reviewed roster, useresolve(until="characters")and review the new roster before continuing. The old checkpoint remains inspectable.series_voice_missing/series_narrator_changed: restore the previous voice or explicitly authorize the corresponding change on.series(...). Resolving first does not bypass write validation; see series.
Intent, output, events, and cancellation
voice_requiredandtts_required: callassign_voice(...).tts()in order.duplicate_operation/invalid_operation_order: create a new immutable branch with each operation once and place chapter selection and voice assignment before TTS.invalid_workers: use"auto"or a positive integer (notTrue/False).invalid_output: use an.m4bpath whose parent directory already exists.output_exists: choose another path or explicitly passoverwrite=True.callback_failed: an event callback raised before publication commit; fix it or remove it. No candidate was published. PublicationStageCompletedand terminalCompletedhappen only after commit and are best-effort, so exceptions from those callbacks are generically logged and do not turn success into failure.cancelled: the supplied token was cancelled. Cancellation is expected to leave no published candidate.
FFmpeg capability or artifact failure
Install FFmpeg 5+ with both commands and AAC support on PATH (see
installation). Stable distinctions are:
ffmpeg_not_found,ffprobe_not_found— executable discovery;ffmpeg_unsupported,ffprobe_unsupported— capability preflight;encoding_failed,cover_failed— candidate construction;probe_failed,decode_failed,invalid_artifact— independent validation;publication_failed— validated candidate could not be atomically published.
A failure never publishes the candidate. To reproduce the explicit native tier:
ffmpeg -version
ffprobe -version
KENKUI_RUN_NATIVE=1 uv run pytest --no-cov -m native tests/test_native_ffmpeg.py
Renderer, Pocket, voice, and synthesis
renderer_unavailable: no manifest atKENKUI_POCKET_MANIFESTor the managed default. Runkk.load_voice("<id>")once. Inspection and validation work without it.voice_not_provisioned: the voice is registered but not loaded. The message names the call that fixes it:kk.load_voice("<id>").voice_unknown: the ID is in neither the built-in catalog nor the manifest.kk.list_voices()shows everything available.engine_not_cloning_capable: awavvoice needs the gatedkyutai/pocket-ttsweights to compile. Accept the terms and authenticate, or supply a pre-compiled.safetensorsinstead.voice_variety_invalid: unrecognised variety or state, or anadd_voiceID that collides with a built-in catalog name.pocket_package_missing:pocket-ttsis a required dependency; reinstall.pocket_version_unsupported: exactly 2.1.0 is required.pocket_model_invalid/pocket_voice_invalid: local manifest/tree/config or prompt/rights declarations failed preflight; do not fall back to a downloader.voice_provenance_required,voice_disabled,voice_incompatible,voice_unresolved: correct the explicit voice registry material.- Pocket model/voice load and inference codes,
synthesis_failed, andinvalid_audio: provider/worker output failed a sanitized execution boundary.
Model and voice assets are provisioned separately. Default tests skip real Pocket inference; the Pocket adapter page describes the opt-in tier and its asset requirements.