makeplane / makeplane/plane

Docs document a work-item relation removal endpoint that does not exist in the API

Open
#9,584 1 comment 0 reactions 0 assignees View on GitHub

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:

  1. Add the documented route to the public API (IssueRelationRemoveSerializer is already written).
  2. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.