POST /api/admin/vocabularies/{id}/terms (add_term in crates/api/src/admin_vocab.rs, merged at c4e0c4c) parses {id} as a VocabularyId and, if the UUID is well-formed but no such vocabulary exists, lets the insert hit a foreign-key violation. That FK error is mapped to 500 Internal Server Error.
A well-formed id pointing at a missing vocabulary is a client error, so the correct status is 404 Not Found (consistent with how the object/term/authority endpoints treat missing/unparseable ids elsewhere). Behaviour is safe today — the transaction rolls back — only the status code is coarse.
Task
In add_term, pre-check vocabulary existence (e.g. db::vocab::vocabulary_by_key/an existence query, or distinguish the FK violation from other sqlx::Errors) and return 404 when the vocabulary is absent.
Keep 500 only for genuine DB failures.
Acceptance
POST /api/admin/vocabularies/<valid-but-unknown-uuid>/terms → 404.
Adding a term to an existing vocabulary still → 201.
A test covers the missing-vocabulary case.
## Context
`POST /api/admin/vocabularies/{id}/terms` (`add_term` in `crates/api/src/admin_vocab.rs`, merged at `c4e0c4c`) parses `{id}` as a `VocabularyId` and, if the UUID is well-formed but no such vocabulary exists, lets the insert hit a foreign-key violation. That FK error is mapped to **500 Internal Server Error**.
A well-formed id pointing at a missing vocabulary is a **client** error, so the correct status is **404 Not Found** (consistent with how the object/term/authority endpoints treat missing/unparseable ids elsewhere). Behaviour is safe today — the transaction rolls back — only the status code is coarse.
## Task
- In `add_term`, pre-check vocabulary existence (e.g. `db::vocab::vocabulary_by_key`/an existence query, or distinguish the FK violation from other `sqlx::Error`s) and return `404` when the vocabulary is absent.
- Keep `500` only for genuine DB failures.
## Acceptance
- `POST /api/admin/vocabularies/<valid-but-unknown-uuid>/terms` → `404`.
- Adding a term to an existing vocabulary still → `201`.
- A test covers the missing-vocabulary case.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Context
POST /api/admin/vocabularies/{id}/terms(add_termincrates/api/src/admin_vocab.rs, merged atc4e0c4c) parses{id}as aVocabularyIdand, if the UUID is well-formed but no such vocabulary exists, lets the insert hit a foreign-key violation. That FK error is mapped to 500 Internal Server Error.A well-formed id pointing at a missing vocabulary is a client error, so the correct status is 404 Not Found (consistent with how the object/term/authority endpoints treat missing/unparseable ids elsewhere). Behaviour is safe today — the transaction rolls back — only the status code is coarse.
Task
add_term, pre-check vocabulary existence (e.g.db::vocab::vocabulary_by_key/an existence query, or distinguish the FK violation from othersqlx::Errors) and return404when the vocabulary is absent.500only for genuine DB failures.Acceptance
POST /api/admin/vocabularies/<valid-but-unknown-uuid>/terms→404.201.