Repository navigation
Mastodon's FeatureRequest (FEP-7aa9) is rejected with 400 Missing actor because it has no actor #1289
Description
Summary
Mastodon 4.6+ sends FEP-7aa9 FeatureRequest activities without an actor property. Fedify's inbox verifies the signatures and then rejects the activity with 400 Missing actor before any inbox listener runs, so a Fedify-based server cannot be added to a Mastodon "Collection".
Environment
@fedify/fedify2.4.2 with@fedify/h3, Node 22- Sender: Mastodon 4.7.2
- Receiver: Moim (https://moim.live), Group actors with
interactionPolicy.canFeatureand a.on(FeatureRequest, …)listener
What happens
A Mastodon user adds a Moim Group to a Collection. The FeatureRequest arrives HTTP-signed and LD-signed, and with debug logging Fedify shows:
[DBG] fedify.federation.inbox: Linked Data Signatures are verified.
[ERR] fedify.federation.inbox: Missing actor.
[WRN] fedify.federation.http: 'POST' '/ap/actors/hackerspub/inbox': 400
The listener is never called. Mastodon treats the 400 as final, so the item stays "pending" forever.
What Mastodon sends, and how the others read it
Mastodon (2b43d597)
- The activity carries only
id,type,objectandinstrument;actoris not serialized:app/serializers/activitypub/feature_request_serializer.rb#L6-L7This matches the FEP-7aa9attributes :id, :type, :instrument attribute :virtual_object, key: :object
FeatureRequestexample, which also has noactor. - Its own inbox never needs the property: the signed-request actor is handed to processing (
inboxes_controller.rb#L93) and becomes@accountfor every activity handler (activity.rb#L12-L14); theFeatureRequesthandler reads@accountonly (activity/feature_request.rb).
Pixelfed (9edda3fa)
actoris optional for this one type:InboxValidator.php#L192-L195and the validator rule ispublic static function actorOptionalFor(array $payload): bool { return isset($payload['type']) && $payload['type'] === 'FeatureRequest'; }
'actor' => 'sometimes|nullable|url'(FeatureRequestValidator.php#L19).- The requester is the HTTP-signature key owner:
HandlesFeatureRequests.php#L85-L91/** * The requester. FeatureRequest usually has no `actor` property, so * fall back to the profile that owns the HTTP signature key. The inbox * validator already verified the signature against that key. */
@fedify/interaction-controls (fea9c751)
featureInteractionalready handles a request withoutactorby taking the requester from the collection'sattributedTo:packages/interaction-controls/src/feature.ts#L43-L45. That code runs inside a listener, which the core inbox never reaches for these activities.
Impact
Any Fedify app implementing the consumer side of FEP-7aa9 is unreachable from Mastodon Collections, which is where these requests come from today. Confirmed on moim.live; Hackers' Pub will hit the same thing when it implements featured actors (hackers-pub/hackerspub#422).
For now Moim runs a local pnpm patch that, for FeatureRequest only, uses the HTTP-signature key owner as the actor (moim-social/moim#183). With it the request is accepted and Mastodon receives the Accept.
AI disclosure
Per AI_POLICY.md: the investigation behind this report (reading the Mastodon, Pixelfed, and Fedify sources, reproducing the failure, and collecting the logs) and the first draft of this text were done with Claude Code (Claude Fable 5.1, claude-fable-5-1). I reviewed and verified the findings against the referenced sources and did the final editing myself.
Assisted-by: Claude Code:claude-fable-5-1
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Effort
Activity
dahlia commentedon Oct 11, 2026
The fix is now targeted for Fedify 2.5 rather than 2.4.3. PR #1291 has been closed without merging, so this bug remains unresolved and the existing actorless-request rejection remains in place.
We initially tried a
FeatureRequest-specific bridge to avoid introducing a general authentication API in a patch release. The review loop showed that safe acceptance still requires a consistent relationship between the authenticated principal, the exact JSON-LD interpretation, the collection's ownership, and queued delivery. Successive fixes addressed individual symptoms, but confirmed parsing and ownership gaps remained. We will address this issue with the shared authentication design in #1290.For the replacement:
actor. A valid signature alone does not authorize a request naming someone else's collection; the requester must match the reliably resolved collection owner.instrumentandattributedTovalues before typed parsing loses anonymous/untyped values, including list containers.FeatureRequestactivities #1291's regression cases across HTTP Signatures, Linked Data Signatures, Object Integrity Proofs, forwarding, and queued delivery.#1291 is a source of test cases, not an implementation ready to merge. The independent loader scheme bug is tracked separately in #1292.