Skip to content

[Bug] Form layout fieldTypeSchema allows 5 types invalid for layout[].fields[], causing opaque CB_VA01 errors #552

Description

@yanoshi-1009

Summary

fieldTypeSchema in src/schema/app/form-layout.ts accepts 5 values that the kintone REST API does not allow at layout[].fields[].type: GROUP, SUBTABLE, STATUS, STATUS_ASSIGNEE, and CATEGORY.

This is not merely cosmetic. GROUP and SUBTABLE are row types (layout[].type), so presenting them as field types leads callers to place a group inside a row. Such a payload passes validation unchanged and is forwarded to kintone, which rejects it with [400] [CB_VA01] Missing or invalid input. — an error that gives the caller no indication of the actual cause.

Affected via layoutForParameterSchema:

  • kintone-update-form-layout (inputSchema)
  • kintone-get-form-layout (outputSchema)

Target Version

v1.9.1

Reproduction

Call kintone-update-form-layout with a group placed inside a row — a shape the current schema presents as valid:

{
  "app": "1",
  "layout": [
    { "type": "ROW", "fields": [ { "type": "GROUP", "code": "group_0" } ] }
  ]
}

type: "GROUP" is an accepted member of fieldTypeSchema and code is a string, so validation passes. The callback forwards layout verbatim to client.app.updateFormLayout(), and kintone responds [400] [CB_VA01] Missing or invalid input. The same applies to SUBTABLE, STATUS, STATUS_ASSIGNEE, and CATEGORY.

An additional note on the more natural payload: a caller that treats GROUP as a field type will usually also supply the group's contents:

{ "type": "ROW", "fields": [ { "type": "GROUP", "code": "group_0", "layout": [ /* rows */ ] } ] }

Here layout is not declared on fieldForParameterSchema, and since z.object() in zod 3.25.76 strips unknown keys by default, it is silently dropped rather than reported — leaving the same invalid { "type": "GROUP", "code": "group_0" } to be sent to kintone.

Expected Behavior

layout[].fields[].type should accept only the 26 values documented for both endpoints:

CALC CHECK_BOX CREATED_TIME CREATOR DATE DATETIME DROP_DOWN FILE GROUP_SELECT HR LABEL LINK MODIFIER MULTI_LINE_TEXT MULTI_SELECT NUMBER ORGANIZATION_SELECT RADIO_BUTTON RECORD_NUMBER REFERENCE_TABLE RICH_TEXT SINGLE_LINE_TEXT SPACER TIME UPDATED_TIME USER_SELECT

A group should only be expressible as a row-level element, which the schema already supports correctly via groupLayoutForParameterSchema.

Actual Behavior

fieldTypeSchema declares 31 literals. The 5 extras are:

Value Why it is not valid at layout[].fields[].type
GROUP A row type (layout[].type), not a field type
SUBTABLE A row type (layout[].type), not a field type
STATUS Not placed on the form layout
STATUS_ASSIGNEE Not placed on the form layout
CATEGORY Not placed on the form layout

Invalid input is accepted at the MCP boundary and only surfaces later as an opaque kintone error.

Suggested fix

Remove the 5 literals from fieldTypeSchema so it matches the 26 documented values.

This is safe for kintone-get-form-layout's outputSchema as well: the Get Form Layout response spec documents the same 26 values, so kintone never returns the removed literals at this position.

This change alone also resolves the silent-drop case described above — once GROUP is no longer an accepted field type, { "type": "GROUP", "code": "...", "layout": [...] } inside fields[] fails immediately on the type literal instead of being partially stripped and forwarded.

Environment

- Operating System: macOS 26.6.1 (arm64)
- Node.js version: v26.2.0
- pnpm version: 11.18.0
- @kintone/mcp-server: 1.9.1 (run via `pnpm dlx @kintone/mcp-server`)
- MCP client: Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions