Skip to content

Bug: Tag taxonomy term picker shows no existing terms when taxonomy is added to a custom collection #1199

Closed

Description

@ahtlv

Description

When enabling the built-in tag taxonomy for a custom collection (not posts), the term picker in the admin editor shows no existing terms — only a "create new" prompt. This makes it impossible to assign pre-existing tags to entries in that collection.

What I was trying to do:
I wanted to use tags to control which projects appear in different page sections (homepage slider, regional landing pages). The plan was:

  • Add the projects collection to the tag taxonomy's collections array
  • Create tag terms like homepage and moskva
  • Assign them to project entries via the admin

What happened:

  1. Updated _emdash_taxonomy_defs via SQL: collections = '[\"posts\",\"projects\"]'
  2. Created terms via SQL with correct translation_group = id
  3. The Tags widget appeared in the project editor ✓
  4. Clicking the tag picker opened an empty picker with only a "create" prompt — existing terms never appeared ✗
  5. After restarting the dev server, same result

Tried both with translation_group = NULL (first attempt) and translation_group = id (second attempt, matching TaxonomyRepository.create() pattern) — no difference in picker behavior.

Root issue: There appears to be no supported way to enable the tag (or category) taxonomy for a custom collection. The collections field on _emdash_taxonomy_defs implies it should work, but the admin term picker does not surface existing terms for non-posts collections even when the data is correctly structured in the database.

Steps to reproduce

  1. Create a custom collection (e.g. projects) via npx emdash schema create
  2. Manually update the tag taxonomy to include the new collection:
    UPDATE _emdash_taxonomy_defs SET collections = '["posts","projects"]' WHERE name = 'tag';
  3. Insert a tag term with correct translation_group:
    INSERT INTO taxonomies (id, name, slug, label, locale, translation_group)
    VALUES ('tag_homepage', 'tag', 'homepage', 'Homepage', 'en', 'tag_homepage');
  4. Restart the dev server
  5. Open the admin, navigate to any projects entry
  6. Click the Tags field — the term picker opens but shows no existing terms, only a "create" prompt

Expected behavior

  • The tag term picker should display existing terms (Homepage, etc.) as selectable options
  • Alternatively: there should be an official CLI command or admin UI to add a taxonomy to a custom collection (e.g. npx emdash schema add-taxonomy projects tag)

Environment

  • emdash: 0.14.0
  • Node.js: 20.x
  • Runtime: @astrojs/node (dev), Cloudflare Workers (prod)
  • OS: macOS

Logs / error output

No errors thrown. The admin picker opens silently with zero terms shown.

Activity

  1. added and removed
    bot:reproMaintainer asked the bot to reproduce this
    on May 29, 2026
  2. emdashbot commented on May 29, 2026

    @emdashbot
    Contributor

    The investigation bot reproduced this issue.

    Root cause (medium confidence): packages/admin/src/components/TaxonomySidebar.tsx:170-176 (the TagInput suggestions memo, plus the related showCreateOption on line 183). For non-hierarchical taxonomies (tag), the picker is a free-text autocomplete: suggestions short-circuits to [] when trimmedInput is empty, and the suggestions dropdown is rendered only when suggestions.length > 0 || showCreateOption. So clicking the Tags field with no text typed produces an empty, invisible picker — there is no list of existing terms and no affordance to discover them. The hierarchical branch in the same file (TaxonomySection, around lines 393–417) renders the full term list up-front, which is why categories appear and tags do not. This produces exactly the symptom reported: "the term picker opens but shows no existing terms, only a create prompt" — they only ever see Create after they start typing, because before typing the dropdown is hidden, and after typing a non-matching prefix only the Create row appears. Whether the taxonomy is attached to posts or to a custom collection is irrelevant; this is a UI affordance defect in the flat (tag-style) picker, not a data/collections-filtering bug. (Server side confirms: handleTermList in packages/core/src/api/handlers/taxonomies.ts:360 doesn't filter terms by collection, and findByName in packages/core/src/database/repositories/taxonomy.ts:128 doesn't either; reproduce verified the API returns the inserted term immediately.)
    Hypotheses considered: Confidence is medium, not high, because the right fix is a design decision rather than a one-line mechanical change. Plausible fixes: (a) render the suggestions dropdown unconditionally on focus and show the first N existing terms when input is empty; (b) keep typing-triggered behaviour but add helper text under the input like "X existing tags — type to filter"; (c) switch the tag picker to a combobox/listbox like the category checkbox tree. A maintainer should pick one. \n\nSecondary contributors that explain why the reporter described it as a complete failure: (1) the React Query cache in TaxonomySidebar (queryKey: ["taxonomy-terms", taxonomy.name]) is not invalidated when terms are inserted out-of-band via raw SQL — only createTermMutation.onSuccess invalidates it. The reporter inserted via SQL, never refreshed, and React Query served a cached empty list. Reproduce confirmed a hard reload fixes that. This is arguably working-as-designed (SQL bypasses the app), but it compounds the UX defect: even after typing, a stale cache yields no suggestion and only the Create row. (2) The reporter's other plausible alternative root cause — that collections filtering hides terms for non-posts collections — was ruled out at reproduce time: typing "w" surfaces "Web Development" once the page is fresh, and the /taxonomies/:name/terms endpoint has no collection filter.\n\nNot considered the cause: server-side cache (invalidateTermCache is a documented no-op), locale filtering (admin requests without ?locale return all locales, and the seeded + inserted terms all use 'en'), or permissions (request returns 200 with terms).
    Verdict: bug — The behaviour in packages/admin/src/components/TaxonomySidebar.tsx:170-185 makes existing tag terms undiscoverable from the picker UI. There is no docstring, no inline comment, no doc page, and no test that asserts "the tag picker intentionally renders nothing until the user types" — the only mock of this component (packages/admin/tests/components/ContentEditor.test.tsx:63-64) replaces it wholesale, asserting nothing about its interactive behaviour. The sibling hierarchical branch in the same file (TaxonomySection, ~lines 393–417) renders every term up front for categories, which is direct internal evidence that the intent is "show what already exists"; the flat branch silently diverges from that intent. The reporter's expectation that clicking the Tags field should reveal existing tags is reasonable and matches the categories UX in the same component. So the behaviour matches the code but the code does not match documented or implied intent: bug.\n\nThat said, the diagnose's medium-confidence call is correct — the fix is a UX design choice (show top N on focus vs. always-open listbox vs. helper text). Per the verify gate, this will not auto-trigger the fix stage; the orchestrator should comment with the diagnosis and let a maintainer pick the resolution shape. The reporter's secondary "no supported way to attach taxonomies to custom collections" claim is separately not a bug — reproduce confirmed the SQL-level mechanism works and the server returns the terms — but the picker UX defect is real.
    The bot reproduced the bug but did not attempt a fix. The fix stage requires verdict: bug AND confidence: high.

    A maintainer will pick up the fix from here.

    Run: https://github.com/emdash-cms/emdash/actions/runs/26635970483

  3. mvanhorn commented on May 31, 2026

    @mvanhorn
    Contributor

    Opened a PR. The tag picker now shows existing terms on focus (not only while typing), with focus/blur open-state handling and a mousedown guard so clicks register before blur closes the list.

  4. added a commit that references this issue on Jun 1, 2026
    b89e988
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions