Skip to content

Timeline Language and Retention Time settings are never applied — read from config_entry.options instead of config_entry.data #700

Description

@catpersec

Checklist

  • I'm running the newest version of LLM Vision https://github.com/valentinfrlch/ha-llmvision/releases/latest
  • I have enabled debug logging for the integration.
  • I have filled out the issue template to the best of my ability.
  • This issue only contains 1 issue (if you have multiple issues, open one issue for each issue).
  • This is a bug and not a feature request.
  • I have searched open issues for my problem.

Describe the issue

The Timeline Language setting (and likely Retention Time) configured under LLM Vision Settings → Reconfigure → Timeline is silently ignored at runtime, no matter what value is selected in the UI. Event classification (category/label columns in events.db) always falls back to English keyword matching, even when the dropdown clearly shows a different language (e.g. Polish) and that value persists across reopening the settings form.

Root cause

The Settings config flow (config_flow.py, async_step_settings) saves the form back to the config entry using:

return self.async_update_reload_and_abort(
    self._get_reconfigure_entry(),
    data_updates=user_input,
)

This writes the selected values (including timeline_language) into config_entry.data.

However, timeline.py reads the language setting from a different attribute:

# timeline.py, line 34
language = config_entry.options.get(CONF_TIMELINE_LANGUAGE) or "English"

config_entry.options is never populated anywhere in the codebase for this entry — every other setting (system_prompt, title_prompt, retention_time in __init__.py, memory paths, provider config, etc.) is consistently read via config_entry.data.get(...). Only two call sites use .options instead:

  • timeline.py:34CONF_TIMELINE_LANGUAGE
  • timeline.py:521CONF_RETENTION_TIME (inconsistent with __init__.py:118, which correctly reads entry.data.get(CONF_RETENTION_TIME))

Because .options is always an empty dict for this entry, .get(CONF_TIMELINE_LANGUAGE) always returns None, so the code always falls back to "English" regardless of what the user configured. This means _get_category_and_label() always loads timeline_strings/en.json, so any non-English word in the event title/description never matches, and category/label stay empty for every user not using English — silently breaking automatic icon assignment in the Timeline Card for every non-English installation.

Expected behavior

category/label should be populated according to the language selected in Settings.

Actual behavior

category/label are always empty (equivalent to always using English matching), regardless of the configured Timeline Language.

Suggested fix

Change timeline.py:34 and timeline.py:521 to read from config_entry.data instead of config_entry.options, matching the rest of the codebase:

language = config_entry.data.get(CONF_TIMELINE_LANGUAGE) or "English"

Reproduction steps

  1. Open LLM Vision Settings → Reconfigure → Timeline and set Language to anything other than English (e.g. Polish).
  2. Save. Reopen the form — the selected language is shown correctly (confirms it is saved somewhere).
  3. Trigger a camera event whose title contains a word that exists in the corresponding timeline_strings/<lang>.json (e.g. Polish "osoba").
  4. Inspect the new row in events.db (or the calendar entity's event data) — category and label are empty strings, even though the word should have matched.

Debug logs

- Verified by direct inspection of `events.db`: an event with description containing a Polish word had empty `category`/`label` before the fix, and correctly populated `category='person', label='person'` after changing `.options` to `.data` at line 34 and restarting.
- Confirmed via source review that every other config value in `__init__.py` and `memory.py` is read via `entry.data.get(...)`, making these two `.options` reads clear outliers rather than intentional design.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions