Bug
kbagent semantic-layer model delete --project <p> --model <m> removes the
model from the metastore but leaves every child entity (semantic-dataset,
semantic-metric, semantic-relationship, semantic-constraint, semantic-glossary)
intact. Because dataset names are unique per project in the metastore, the
next Build or Import that emits a dataset with the same name fails with
HTTP 422 "semantic-dataset with name 'X' already exists in the target model"
even though the user just deleted what they think was the only owner.
Reproduction (no fork, ran on padak-2-0-master)
# 1) Build a small model
kbagent semantic-layer build --project padak-2-0-master \
--tables "in.c-keboola-ex-db-mysql.addresses" --name temp_model
# 2) Delete it via the documented command
kbagent semantic-layer model delete --project padak-2-0-master --model temp_model --yes
# → "Deleted model temp_model (019e36dd-7edb-...)"
# 3) Verify orphans on the wire
TOKEN=$(jq -r '.projects."padak-2-0-master".token' ~/.config/keboola-agent-cli/config.json)
curl -s -H "X-StorageApi-Token: $TOKEN" \
'https://metastore.keboola.com/api/v1/repository/semantic-dataset' \
| jq '.data[] | select(.attributes.name=="addresses")'
# → still returns an item whose modelUUID points at the deleted model
# 4) Trying to rebuild now fails:
kbagent semantic-layer build --project padak-2-0-master \
--tables "in.c-keboola-ex-db-mysql.addresses" --name another_model
# → "build_model push failed at datasets/'addresses': API error 422 ...
# semantic-dataset with name 'addresses' already exists in the target model"
Where it lives
services/semantic_layer_service.py::SemanticLayerService.delete_model
(parent UUID -> client.delete_item("semantic-model", model_uuid)).
The service correctly lists children via _fetch_children_parallel to
populate orphaned_children in the response envelope, then deletes only
the model itself. The children become wire-level orphans.
Suggested fix
In delete_model, delete each child before deleting the parent, in the
reverse of PUSH_ORDER:
for type_name in reversed(PUSH_ORDER): # constraints → glossary → ... → datasets
for child in children.get(type_name[0], []):
client.delete_item(type_name[1], child["id"])
client.delete_item("semantic-model", model_uuid)
Return shape stays the same; the existing orphaned_children counts
become a record of what was cascaded rather than what was leaked.
Severity
Medium. Workflow-breaking for the Build / Import flows users will hit
most often. Workaround today is to enumerate semantic-* repository
endpoints and delete by UUID, which is exactly what no normal user will
do unaided.
Discovered during
UI smoke test of the new Semantic Layer page (feat/semantic-layer-ui)
on padak-2-0-master. Surfaced after the new http_base error-body
parser started rendering the real metastore message instead of bare
"API error 422: 422" — this bug was already there, just invisible.
Bug
kbagent semantic-layer model delete --project <p> --model <m>removes themodel from the metastore but leaves every child entity (semantic-dataset,
semantic-metric, semantic-relationship, semantic-constraint, semantic-glossary)
intact. Because dataset names are unique per project in the metastore, the
next
BuildorImportthat emits a dataset with the same name fails withHTTP 422 "semantic-dataset with name 'X' already exists in the target model"
even though the user just deleted what they think was the only owner.
Reproduction (no fork, ran on padak-2-0-master)
Where it lives
services/semantic_layer_service.py::SemanticLayerService.delete_model(parent UUID ->
client.delete_item("semantic-model", model_uuid)).The service correctly lists children via
_fetch_children_paralleltopopulate
orphaned_childrenin the response envelope, then deletes onlythe model itself. The children become wire-level orphans.
Suggested fix
In
delete_model, delete each child before deleting the parent, in thereverse of
PUSH_ORDER:Return shape stays the same; the existing
orphaned_childrencountsbecome a record of what was cascaded rather than what was leaked.
Severity
Medium. Workflow-breaking for the Build / Import flows users will hit
most often. Workaround today is to enumerate semantic-* repository
endpoints and delete by UUID, which is exactly what no normal user will
do unaided.
Discovered during
UI smoke test of the new Semantic Layer page (
feat/semantic-layer-ui)on padak-2-0-master. Surfaced after the new
http_baseerror-bodyparser started rendering the real metastore message instead of bare
"API error 422: 422" — this bug was already there, just invisible.