This topic was automatically generated from Slack. You can find the original thread here.
Hey there. The airtable_oauth create-field action (and create-table) is failing for us. The action runs, but Airtable’s API comes back 404 NOT_FOUND on the create-field request, so no field is ever created.
It looks specific to the schema/metadata actions, not a broader Airtable or auth problem. On the exact same connected account, base, and table, the record actions (update-record, create-or-update-record, get-record) all work fine. The connected account has the schema.bases:write scope granted. And we get the same 404 whether we call it through the MCP server or the Connect REST actions.run path, so it does not look like a routing issue on our side.
DThe field is a plain singleLineText. Airtable returns a 21 byte {“error”:“NOT_FOUND”} body, attribution origin upstream_api.
Is the create-field component hitting a stale or wrong Airtable metadata endpoint, or is there a base-access requirement for the schema API that the data API does not need? Trying to work out what changed and how to get field and table creation working.
Happy to share request IDs, the full response, or screenshots via DM.
Their API docs unfortunately don’t explain much about how you’d run into a 404. The endpoint is /meta/bases/${baseId}/tables/${tableId}/fields so my natural assumption would be that either the base or the table were what prompted the 404.
Drove this to root cause on our side. It reproduces, and it is in the component, not Airtable and not permissions.
Root cause: the Airtable metadata actions read the base and table ids inconsistently across the component family.
create-field, update-field, and update-table read this.baseId.value and this.tableId.value, which assumes the prop value is a labeled object like { label, value }.
create-table reads this.baseId directly (a bare string).
The record actions in common/actions.mjs read ctx.baseId?.value ?? ctx.baseId, so they tolerate both shapes. That is why record operations always worked.
Why it does not reproduce in the visual builder: when you select a base or table from a dropdown, the value is stored as a labeled { label, value } object, so this.baseId.value resolves and create-field succeeds.
The bug only appears when the component runs via the Connect API (actions.run) or MCP, where the ids arrive as plain strings. That matches the component’s own configured schema, where baseId and tableId are declared as type string. With a plain string, this.baseId.value is undefined, so the component calls /v0/meta/bases/undefined/tables/undefined/fields and Airtable returns the 21 byte {“error”:“NOT_FOUND”} with origin upstream_api.
Repro on your end:
Use any base where the connected account has Creator permission.
Call airtable_oauth-create-field via actions.run with configuredProps.baseId and configuredProps.tableId as plain id strings, plus name and type. You get the 404.
Pass the same ids as { label: id, value: id } objects instead. It succeeds and creates the field.
We confirmed the same matrix for update-field and update-table (404 on plain strings, success on labeled objects), and the inverse for create-table (succeeds on a plain string, 404s on a labeled object).
We also ruled out Airtable and permissions by calling Airtable’s metadata API directly with the same connected account through the Connect proxy. The direct create-field POST succeeds, and the account reports permissionLevel create on the base.
Suggested fix: have the metadata actions read this.baseId?.value ?? this.baseId and this.tableId?.value ?? this.tableId, matching your own record actions in common/actions.mjs. That fixes create-field, update-field, and update-table on the API path, and also removes the inverse fragility in create-table.
Btw, the expected input format -is- an object with { label, value } since the component provides these as options that you’d retrieve via configure component prop. So this is not really a bug, but I understand it’s an inconvenience when most components don’t use withLabel and thus work as expected when passing a raw value (rather than the full { label, value } object that would be retrieved).
We’ve noted this as something to follow up on and improve. The fallback reads should serve just fine though.
Confirmed working now, thanks for the quick turnaround. On the same connected account and base, create-field, update-field, update-table, and create-table all succeed through the Connect actions.run path with raw string ids. The fallback reads do the job.
Appreciate the note on the withLabel context too. Passing the full { label, value } object is fine when props are retrieved via configure-component, but a lot of API and MCP consumers pass the raw id, so the fallback makes those work out of the box. Thanks again for getting this out fast.