Docs document a work-item relation removal endpoint that does not exist in the API
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 59.6k
- Forks
- 5.8k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 49
Description
The API reference documents an endpoint for removing a work-item relation:
https://developers.plane.so/api-reference/work-item-relations/remove-work-item-relation
POST /api/v1/workspaces/{workspace_slug}/projects/{project_id}/work-items/{work_item_id}/relations/remove/
{"related_issue": "<uuid>"}
That route is not registered anywhere in this repository, so it returns 404 on self-hosted instances.
What the code actually has
apps/api/plane/api/urls/work_item.py registers exactly one relations route:
path(
"workspaces/<str:slug>/projects/<uuid:project_id>/work-items/<uuid:issue_id>/relations/",
IssueRelationListCreateAPIEndpoint.as_view(http_method_names=["get", "post"]),
name="work-item-relation-list",
),
IssueRelationListCreateAPIEndpoint (apps/api/plane/api/views/issue.py) defines get and post and nothing else. relations/remove does not appear anywhere in the tree.
Curiously, the serializer for the documented request body does exist — IssueRelationRemoveSerializer in apps/api/plane/api/serializers/issue.py, with a related_issue UUID field and the exact help text from the docs page. It is not imported anywhere, not exported from serializers/__init__.py, and not referenced by any view. It looks like the request shape was ported over but the endpoint that would consume it was not.
There is a relations/remove/ route on commit 801b3315d, but it was never merged (only on fix/comments-mention, in no tag), and it uses the issues/ prefix rather than the work-items/ prefix the docs advertise.
Versions checked
The relations list/create route arrived in #8763 and first shipped in v1.3.0. I checked v0.28.0, v1.0.0, v1.1.0, v1.2.0, v1.2.3, v1.3.0, v1.3.1, v1.4.0 and v1.4.1 — the remove sub-route is in none of them.
Reproduction
Against a self-hosted instance, with a personal API key:
# works — creates the relation, and the inverse edge
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
"$HOST/api/v1/workspaces/$WS/projects/$PROJ/work-items/$ID/relations/" \
-d '{"relation_type": "blocked_by", "issues": ["'"$OTHER"'"]}'
# works — returns the relation-type-keyed object
curl -H "X-API-Key: $KEY" \
"$HOST/api/v1/workspaces/$WS/projects/$PROJ/work-items/$ID/relations/"
# 404 {"error": "Page not found."}
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
"$HOST/api/v1/workspaces/$WS/projects/$PROJ/work-items/$ID/relations/remove/" \
-d '{"related_issue": "'"$OTHER"'"}'
Impact
Relations can be created and read through the public API but never removed, so an integration can build a dependency graph and cannot correct it. The only working path is the internal app API:
POST /api/workspaces/{slug}/projects/{project_id}/issues/{issue_id}/remove-relation/
which uses BaseSessionAuthentication and so rejects an X-API-Key. That makes it unusable from a CLI or server-to-server integration.
Either implementation would resolve this — please just let us know which, so integrations can target the right one:
- Add the documented route to the public API (
IssueRelationRemoveSerializeris already written). - Correct the docs to state that removal is not available in v1, so nobody builds against a page that describes an endpoint that isn't there.
One incidental note
If the endpoint is implemented by reusing IssueRelationViewSet.remove_relation (apps/api/plane/app/views/issue/relation.py), that handler calls .first() and then .delete() with no None check, so removing a relation that doesn't exist raises AttributeError → HTTP 500 rather than a 404.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with apps/api/plane/api/urls/work_item.py, IssueRelationListCreateAPIEndpoint in apps/api/plane/api/views/issue.py, and IssueRelationRemoveSerializer in apps/api/plane/api/serializers/issue.py. Confirm the public route and authentication behavior, then resolve whether the endpoint should be implemented or the documentation corrected. Done means the documented API contract matches a tested, usable behavior, including nonexistent-relation handling if removal is implemented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100