Summary
Submitting a type: 'modal' action fails with "Error loading form — Bad Request". The Console resolves the action's target as an object name and issues GET /api/v1/meta/object/<target>, which 400s because target names a page, not an object.
Per the spec, that is the wrong lookup:
type: 'modal' — target is required (the modal/page name to open).
— @objectstack/spec/dist/action.zod-*.d.ts, Action target docs
Environment
Steps to reproduce
- Declare a modal action and a matching page:
exportconstLogCallAction: Action={name: 'log_call',label: 'Log a Call',type: 'modal',target: 'log_call',// ← the modal PAGE name, per specbody: {language: 'js',source: `/* insert a record */`,capabilities: ['api.write']},locations: ['record_header'],params: [{name: 'subject',label: 'Call Subject',type: 'text',required: true},{name: 'duration',label: 'Duration (minutes)',type: 'number',required: true},{name: 'notes',label: 'Call Notes',type: 'textarea'},],};// registered pageexportconstLogCallPage: Page={name: 'log_call',type: 'utility',/* … */};- Open a record, click Log a Call.
- The modal opens and the params form renders correctly from
params. - Fill it in, press 确认 / Confirm.
Expected
The action body executes with the collected input, and the record is written.
Actual
The modal body is replaced with:
Error loading form
Bad Request
Network:
GET /api/v1/meta/object/log_call → 400 Bad Request
The body never runs; nothing is written.
Scope
Reproduced on every modal action in the app — log_call, log_meeting, create_campaign, escalate_case, close_case, mass_update_stage, send_email. A freshly authored one fails identically (GET /api/v1/meta/object/schedule_followup → 400), so it is not about any particular page definition.
The params form rendering correctly but the submit path resolving target differently suggests two code paths that disagree about what target means: the render path treats it as a page (correct), the submit path as an object.
Impact
Modal actions are the natural shape for "collect a couple of fields and write something" — the most common custom action in a business app. None of them can be completed. The only workaround we found is to re-author each one as a type: 'flow' screen flow.
Related
Screen flows are also un-completable from the Console (Submit never calls the resume endpoint) — filed separately. Together these make every interactive custom action in the app non-functional.
Summary
Submitting a
type: 'modal'action fails with "Error loading form — Bad Request". The Console resolves the action'stargetas an object name and issuesGET /api/v1/meta/object/<target>, which 400s becausetargetnames a page, not an object.Per the spec, that is the wrong lookup:
Environment
@objectstack/*16.1.0objectstack dev), wasm sqliteSteps to reproduce
params.Expected
The action body executes with the collected
input, and the record is written.Actual
The modal body is replaced with:
Network:
The body never runs; nothing is written.
Scope
Reproduced on every modal action in the app —
log_call,log_meeting,create_campaign,escalate_case,close_case,mass_update_stage,send_email. A freshly authored one fails identically (GET /api/v1/meta/object/schedule_followup → 400), so it is not about any particular page definition.The params form rendering correctly but the submit path resolving
targetdifferently suggests two code paths that disagree about whattargetmeans: the render path treats it as a page (correct), the submit path as an object.Impact
Modal actions are the natural shape for "collect a couple of fields and write something" — the most common custom action in a business app. None of them can be completed. The only workaround we found is to re-author each one as a
type: 'flow'screen flow.Related
Screen flows are also un-completable from the Console (Submit never calls the resume endpoint) — filed separately. Together these make every interactive custom action in the app non-functional.