# Parent Label Error Fix
## Problem
Linear.app organizes labels hierarchically, where some labels act as **parent/group labels** that cannot be directly assigned to issues. Previously, attempting to assign a parent label would result in a cryptic error:
```
McpError: MCP error -32603: Failed to create issue: LabelIds contain parent labels -
The label 'Module' is a group and cannot be assigned to issues directly.
```
This was frustrating because:
1. The error occurred after the user had already prepared the issue data
2. There was no way to know which labels were parents before attempting assignment
3. The workflow was interrupted, requiring manual intervention
## Solution
The MCP Linear Server now includes **automatic parent label filtering** with three key improvements:
### 1. Automatic Label Validation
Before creating or updating an issue, the server:
- Fetches each label to check if it has children (making it a parent)
- Filters out parent labels automatically
- Continues with only valid (non-parent) labels
### 2. Clear Warning Messages
When parent labels are filtered, users receive a helpful warning:
```json
{
"id": "abc123",
"identifier": "ENG-456",
"title": "My Issue",
"warnings": [
"Skipped parent labels (cannot be assigned directly): Module, Location. Use linear_list_labels to find child labels."
]
}
```
### 3. Enhanced Label Listing
The `linear_list_labels` tool now shows label hierarchy:
```json
{
"count": 23,
"regularLabelsCount": 18,
"parentLabelsCount": 5,
"note": "Parent labels (isParent: true) cannot be assigned to issues directly. Use their child labels instead.",
"labels": [
{
"id": "label-123",
"name": "Module",
"color": "#bec2c8",
"isParent": true,
"childrenNames": ["Module/Auth", "Module/API", "Module/Frontend"]
},
{
"id": "label-456",
"name": "Module/Auth",
"color": "#bec2c8",
"isParent": false,
"parentName": "Module"
}
]
}
```
## Technical Implementation
### LinearAPIClient.filterParentLabels()
New method that validates label IDs:
```typescript
async filterParentLabels(labelIds: string[]): Promise<{
validLabelIds: string[];
parentLabels: Array<{ id: string; name: string }>;
}> {
// For each label ID:
// 1. Fetch the label from Linear API
// 2. Check if it has children (making it a parent)
// 3. Separate into valid vs parent labels
// 4. Return both lists
}
```
### Enhanced createIssue() and updateIssue()
Both methods now:
1. Call `filterParentLabels()` before creating/updating
2. Use only valid label IDs in the Linear API call
3. Add warning messages to the response if parent labels were filtered
### Enhanced formatLabelsWithHierarchy()
Label listing now includes:
- `isParent`: Boolean indicating if label is a parent/group
- `parentName`: Name of parent label (for child labels)
- `childrenNames`: Array of child label names (for parent labels)
## Usage Examples
### Before the Fix
```typescript
// User tries to create an issue with parent label
linear_create_issue({
title: 'New Feature',
teamId: 'team-123',
labelIds: ['module-parent-id'], // Parent label
});
// Result: ❌ Error!
// McpError: MCP error -32603: LabelIds contain parent labels
```
### After the Fix
```typescript
// User tries to create an issue with parent label
linear_create_issue({
title: "New Feature",
teamId: "team-123",
labelIds: ["module-parent-id", "feature-id"] // Mixed parent + valid
})
// Result: ✅ Success with warning!
{
"success": true,
"message": "Issue created: ENG-789 - New Feature",
"issue": {
"id": "issue-789",
"identifier": "ENG-789",
"title": "New Feature",
"labels": [
{ "id": "feature-id", "name": "Feature" } // Only valid label assigned
],
"warnings": [
"Skipped parent labels (cannot be assigned directly): Module. Use linear_list_labels to find child labels."
]
}
}
```
### Finding Child Labels
```typescript
// Step 1: List all labels to see hierarchy
linear_list_labels()
// Response shows:
{
"labels": [
{
"id": "module-parent-id",
"name": "Module",
"isParent": true,
"childrenNames": ["Module/Auth", "Module/API", "Module/Frontend"]
},
{
"id": "module-auth-id",
"name": "Module/Auth",
"isParent": false,
"parentName": "Module"
}
]
}
// Step 2: Use child label instead
linear_create_issue({
title: "Auth Feature",
teamId: "team-123",
labelIds: ["module-auth-id"] // Child label - works!
})
```
## Error Handling
The fix includes enhanced error messages for any remaining edge cases:
**Before:**
```
Failed to create issue: LabelIds contain parent labels
```
**After:**
```
Failed to create issue: The label 'Module' is a parent/group label and cannot be assigned directly.
Please use one of its child labels instead. Use linear_list_labels to see available labels.
```
## Performance Considerations
### API Calls
The `filterParentLabels()` method makes one API call per label to check for children. For typical usage (1-5 labels per issue), this adds minimal overhead:
- **1 label**: +1 API call
- **3 labels**: +3 API calls
- **5 labels**: +5 API calls
### Optimization Opportunities (Future)
For high-volume usage, consider:
1. **Caching**: Cache parent/child label relationships (they change infrequently)
2. **Batch Fetching**: Use GraphQL to fetch all labels with children in one query
3. **Client-Side Filtering**: Let MCP clients cache label hierarchy
## Testing
### Manual Testing Steps
1. **List labels to find a parent label:**
```typescript
linear_list_labels();
// Find a label with isParent: true
```
2. **Try creating an issue with the parent label:**
```typescript
linear_create_issue({
title: 'Test Issue',
teamId: 'your-team-id',
labelIds: ['parent-label-id'],
});
// Should succeed with warning message
```
3. **Verify the issue was created without the parent label:**
```typescript
linear_get_issue({ issueId: 'TEAM-123' });
// Check labels array - should be empty or contain only valid labels
```
4. **Try with mixed parent and valid labels:**
```typescript
linear_create_issue({
title: 'Test Issue 2',
teamId: 'your-team-id',
labelIds: ['parent-label-id', 'valid-label-id'],
});
// Should succeed with warning, valid label assigned
```
### Expected Behavior
| Scenario | Expected Result |
| -------------------- | ----------------------------------------------------- |
| No labels | Issue created normally, no warnings |
| Only valid labels | Issue created with all labels, no warnings |
| Only parent labels | Issue created with no labels, warning message |
| Mixed parent + valid | Issue created with valid labels only, warning message |
| Invalid label ID | Error from Linear API (label not found) |
## Migration Guide
### For Existing Users
No action required! The fix is **backward compatible**:
- Existing code continues to work
- Issues with valid labels are unaffected
- Only parent label attempts now show warnings instead of errors
### For New Integrations
**Best Practice:**
1. Use `linear_list_labels` to discover label hierarchy
2. Cache label IDs for frequently used labels
3. Use child labels in your automation
4. Monitor warnings in responses to catch accidental parent label usage
## Files Changed
1. **src/linear-client.ts**
- Added `filterParentLabels()` method
- Enhanced `createIssue()` with label validation
- Enhanced `updateIssue()` with label validation
- Improved `getErrorMessage()` for parent label errors
- Added `formatLabelsWithHierarchy()` method
2. **src/tools/labels.ts**
- Updated `listLabels()` to show hierarchy information
- Added counts for regular vs parent labels
- Added helpful note about parent labels
3. **README.md**
- Added troubleshooting section for parent label errors
- Included usage examples
4. **CHANGELOG.md**
- Documented the fix in "Unreleased" section
## Related Documentation
- [Linear API Label Documentation](https://developers.linear.app/docs/graphql/working-with-labels)
- [README.md - Troubleshooting](../README.md#troubleshooting)
- [CHANGELOG.md](./CHANGELOG.md)
## Future Improvements
Potential enhancements for future versions:
1. **Caching**: Cache label hierarchy for performance
2. **Validation Tool**: New `linear_validate_labels` tool to check labels before use
3. **Auto-Select Child**: Automatically select first child label if parent is provided
4. **Batch Validation**: GraphQL query to validate multiple labels at once
5. **Label Recommendations**: Suggest child labels when parent is detected