GraphQL mutation design including payload patterns, field-specific errors, input objects, and HTTP semantics. Use when designing or implementing GraphQL mutations.
Installation
Details
Usage
After installing, this skill will be available to your AI coding assistant.
Verify installation:
npx agent-skills-cli listSkill Instructions
name: graphql-mutations description: GraphQL mutation design including payload patterns, field-specific errors, input objects, and HTTP semantics. Use when designing or implementing GraphQL mutations.
GraphQL Mutations
Expert guidance for designing effective GraphQL mutations.
Quick Reference
| Pattern | Use When | Structure |
|---|---|---|
| Result payload | All mutations | mutationName(input): MutationNamePayload! |
| Field-specific errors | Validation failures | errors: [FieldError!]! in payload |
| Input objects | Complex arguments | input: MutationNameInput! |
| Noun + Verb naming | State changes | createUser, deletePost, closeCard |
| Idempotent mutations | Safe retries | Design for repeatable calls |
| Optimistic UI | Client-side updates | Return predicted result |
What Do You Need?
- Payload design - Return types, error handling
- Input objects - Structuring mutation arguments
- Error patterns - Field-specific vs top-level errors
- Naming - Mutation naming conventions
- Side effects - Handling async operations
Specify a number or describe your mutation scenario.
Routing
| Response | Reference to Read |
|---|---|
| 1, "payload", "return", "response" | payloads.md |
| 2, "input", "argument", "parameter" | inputs.md |
| 3, "error", "validation", "field error" | errors.md |
| 4, "naming", "convention" | naming.md |
| 5, general mutations | Read relevant references |
Critical Rules
- Always return a payload: Never just a boolean or the object
- Use input objects for complex arguments: Don't use many scalars
- Field-specific errors in response: Let clients handle per-field failures
- Noun + verb naming: createUser, deleteUser, not user
- Mutations are POST-only: Never use GET for mutations
- Design for idempotency: Safe to call multiple times
Mutation Template
# Input object for complex arguments
input CreateUserInput {
name: String!
email: String!
password: String!
}
# Payload with result and errors
type CreateUserPayload {
user: User
errors: [UserError!]!
}
# Field-specific error type
type UserError {
field: [String!]! # Path to field: ["email"] or ["user", "emails", 0]
message: String!
}
# Mutation definition
type Mutation {
"""
Creates a new user account
"""
createUser(input: CreateUserInput!): CreateUserPayload!
}
Mutation Implementation
// Good: Mutation with proper payload and field errors
func (r *mutationResolver) CreateUser(ctx context.Context, input CreateUserInput) (*CreateUserPayload, error) {
// Validate
var errs []UserError
if input.Name == "" {
errs = append(errs, UserError{
Field: []string{"name"},
Message: "Name is required",
})
}
if !isValidEmail(input.Email) {
errs = append(errs, UserError{
Field: []string{"email"},
Message: "Invalid email format",
})
}
if len(errs) > 0 {
return &CreateUserPayload{Errors: errs}, nil
}
// Create
user, err := r.db.CreateUser(input)
if err != nil {
if errors.Is(err, db.ErrDuplicate) {
return &CreateUserPayload{
Errors: []UserError{{
Field: []string{"email"},
Message: "Email already exists",
}},
}, nil
}
return nil, fmt.Errorf("failed to create user")
}
return &CreateUserPayload{User: user, Errors: []UserError{}}, nil
}
Common Mutation Patterns
Create
type Mutation {
createUser(input: CreateUserInput!): CreateUserPayload!
}
type CreateUserPayload {
user: User
errors: [UserError!]!
}
Update
type Mutation {
updateUser(id: ID!, input: UpdateUserInput!): UpdateUserPayload!
}
type UpdateUserPayload {
user: User
errors: [UserError!]!
}
Delete
type Mutation {
deleteUser(id: ID!): DeleteUserPayload!
}
type DeleteUserPayload {
deletedUserId: ID
errors: [UserError!]!
}
State Change (Noun + Verb)
type Mutation {
"""
Closes a card (marks as closed, not deleted)
"""
closeCard(id: ID!): CloseCardPayload!
}
type CloseCardPayload {
card: Card
errors: [UserError!]!
}
Error Handling Patterns
| Error Type | Response Pattern |
|---|---|
| Validation errors | Return in payload errors field |
| Duplicate unique key | Return in payload errors field |
| Not found | Return in payload errors field |
| Permission denied | Return in payload errors field |
| Internal server error | Return nil, wrap error (don't expose) |
HTTP Semantics
| Concern | Guidance |
|---|---|
| HTTP method | Always POST for mutations |
| Caching | Mutations are never cached |
| Idempotency | Design mutations to be safely repeatable |
| Side effects | Document non-obvious side effects |
| Async operations | Return payload with job ID, query for status |
Common Mutation Mistakes
| Mistake | Severity | Fix |
|---|---|---|
| Returning just boolean | Medium | Use payload with result |
| No field-specific errors | High | Add errors array to payload |
| Too many scalar arguments | Medium | Use input object |
| Verb + noun naming | Low | Use noun + verb (createUser) |
| Using GET for mutations | Critical | Always use POST |
| No validation errors in payload | High | Return validation failures |
Reference Index
| File | Topics |
|---|---|
| payloads.md | Result types, error patterns, response structure |
| inputs.md | Input objects, nested inputs, validation |
| errors.md | Field errors, error types, client handling |
| naming.md | Conventions, verb selection, consistency |
Success Criteria
Mutations are well-designed when:
- All mutations return a payload type
- Field-specific errors returned in payload
- Input objects used for complex arguments
- Noun + verb naming (createUser, deletePost)
- POST only (never GET)
- Idempotent where possible
- Validation errors returned, not thrown
- No internal errors exposed to clients
More by jovermier
View allNext.js App Router Server Components, Client Components, layouts, data fetching, and Server Actions. Use when working with Next.js app directory, component boundaries, or data fetching patterns.
Go error handling patterns including wrapping, custom error types, errors.Is/As, and error conventions. Use when handling, creating, or checking errors in Go.
Automatically discover and install relevant skills from SkillsMP and other sources
Next.js Metadata API for SEO, OpenGraph tags, structured data, and social sharing. Use when implementing metadata, SEO, or social media previews.
