Creating Diagnostic Error Codes
March 29, 2026 ยท View on GitHub
A guide for adding new diagnostic error codes to the Minecraft Bedrock Language Server.
Quick Start
- Choose error code location based on type (behavior pack, resource pack, general, minecraft-specific)
- Follow naming convention:
category.subcategory.type.detail - Use
diagnoser.add()with position, message, severity, and code - Test your diagnostic
Table of Contents
Overview
The diagnostic system provides error checking and validation for Minecraft Bedrock projects. It helps developers identify issues in behavior packs, resource packs, and other project files.
Package: packages/bedrock-diagnoser
Architecture
Core Interfaces
| Interface | Purpose |
|---|---|
| DiagnosticsBuilder | Main interface with add() method for adding diagnostics |
| DocumentDiagnosticsBuilder | Extension for document-specific diagnostics |
| DiagnosticSeverity | Severity levels: error, warning, info, hint |
๐ Location: packages/bedrock-diagnoser/src/types/diagnostics-builder.ts
File Organization
Diagnostics are organized by category:
packages/bedrock-diagnoser/src/diagnostics/
โโโ behavior-pack/ # Behavior pack diagnostics
โ โโโ animation/
โ โโโ entity/
โ โโโ mcfunction/
โ โโโ ...
โโโ resource-pack/ # Resource pack diagnostics
โ โโโ animation/
โ โโโ sounds/
โ โโโ ...
โโโ general/ # Generic validation (integers, floats, etc.)
โโโ minecraft/ # Minecraft-specific (selectors, effects, etc.)
โโโ molang/ # Molang expression diagnostics
โโโ errors/ # Common error utilities
Naming Conventions
Format Pattern
<category>.<subcategory>.<type>.<detail>
Categories
| Category | Use For |
|---|---|
behaviorpack | Behavior pack issues |
resourcepack | Resource pack issues |
general | Generic validation (types, formats) |
minecraft | Minecraft concepts (selectors, effects, tags) |
json | JSON parsing/validation |
diagnostics | Internal system issues |
Common Type Suffixes
| Suffix | Meaning |
|---|---|
.missing | Resource/definition not found |
.invalid | Invalid syntax or value |
.deprecated | Deprecated feature |
.minimum / .maximum | Value range violation |
.duplicate | Duplicate definition |
Examples
'behaviorpack.entity.event.missing' // Missing entity event
'resourcepack.animation.missing' // Missing animation
'general.integer.invalid' // Invalid integer
'minecraft.selector.invalid' // Invalid selector
'general.integer.minimum' // Below minimum
'general.integer.maximum' // Above maximum
Step-by-Step Guide
1๏ธโฃ Identify Location
Choose the appropriate directory:
| Type | Directory |
|---|---|
| Behavior pack | diagnostics/behavior-pack/ |
| Resource pack | diagnostics/resource-pack/ |
| General validation | diagnostics/general/ |
| Minecraft-specific | diagnostics/minecraft/ |
2๏ธโฃ Create or Locate Function
Find or create the diagnostic function file:
// Example: packages/bedrock-diagnoser/src/diagnostics/behavior-pack/entity/diagnose.ts
3๏ธโฃ Add Diagnostic Call
Use diagnoser.add() with four parameters:
diagnoser.add(
position, // string path or DocumentLocation
message, // Human-readable error message
severity, // DiagnosticSeverity enum
code // Error code string
);
4๏ธโฃ Choose Severity
See Severity Levels section.
5๏ธโฃ Write Clear Messages
โ Good messages:
- Concise and descriptive
- Explain what's wrong
- Suggest fixes when possible
- Include relevant context
6๏ธโฃ Test
- Create test file with problematic code
- Run diagnostic system
- Verify error reported correctly
- Test edge cases
Severity Levels
๐ด Error
When to use: Issues that will definitely cause runtime problems
Examples:
- Missing required resources
- Invalid syntax Minecraft can't parse
- Type mismatches
- Security vulnerabilities
diagnoser.add(
value,
`Cannot find entity definition: ${id}`,
DiagnosticSeverity.error,
'behaviorpack.entity.missing'
);
๐ก Warning
When to use: Issues that might cause problems or are bad practice
Examples:
- Missing optional resources
- Deprecated features
- Component groups not found
diagnoser.add(
path,
`Event uses deprecated run_command, use queue_command instead`,
DiagnosticSeverity.warning,
'behaviorpack.entity.event.run_command'
);
๐ต Info
When to use: Suggestions and optimization opportunities
Examples:
- Unnecessary code
- Performance improvements
- Style suggestions
diagnoser.add(
event_id,
"'randomize' only has one entry and can be removed",
DiagnosticSeverity.info,
'behaviorpack.entity.event.randomize.length'
);
โช Hint
When to use: Subtle suggestions that don't impact functionality
Examples:
- Code style preferences
- Minor optimizations
Best Practices
โ Do's
| Practice | Example |
|---|---|
| Use consistent codes | Follow category.subcategory.type pattern |
| Be specific | Include problematic value in message |
| Be concise | Keep messages short and clear |
| Suggest fixes | Tell user how to resolve the issue |
| Reuse functions | Use existing utilities like Errors.missing() |
โ Don'ts
| Anti-pattern | Why |
|---|---|
| Vague messages | "Error" tells user nothing |
| Generic codes | "error" doesn't categorize |
| Missing context | User can't identify the problem |
| Overly long messages | Hard to read in IDE |
Message Examples
// โ Bad: Vague
diagnoser.add(value, 'Error', DiagnosticSeverity.error, 'error');
// โ
Good: Clear and specific
diagnoser.add(
value,
`Cannot find behavior pack animation: ${id}`,
DiagnosticSeverity.error,
'behaviorpack.animation.missing'
);
// โ Bad: No context
diagnoser.add(value, 'Invalid value', DiagnosticSeverity.error, 'invalid');
// โ
Good: Shows problematic value
diagnoser.add(
value,
`Invalid integer value: ${value.text}`,
DiagnosticSeverity.error,
'general.integer.invalid'
);
Position Types
// Object property path
diagnoser.add('events/my_event/trigger', message, severity, code);
// Text offset (OffsetWord)
diagnoser.add(value, message, severity, code);
// Document location
diagnoser.add({ line: 10, character: 5 }, message, severity, code);
Reuse Utilities
Create reusable functions for common patterns:
export function general_integer_diagnose(
value: Types.OffsetWord,
diagnoser: DiagnosticsBuilder,
range?: { min: number; max: number }
): boolean {
if (General.Integer.is(value.text)) {
if (range) {
const v = Number.parseInt(value.text);
if (v < range.min) {
diagnoser.add(
value,
`The value of ${v} is lower than the allowed minimum: ${range.min}`,
DiagnosticSeverity.error,
'general.integer.minimum'
);
}
if (v > range.max) {
diagnoser.add(
value,
`The value of ${v} is higher than the allowed maximum: ${range.max}`,
DiagnosticSeverity.error,
'general.integer.maximum'
);
}
}
return true;
}
diagnoser.add(
value,
`Invalid integer value: ${value.text}`,
DiagnosticSeverity.error,
'general.integer.invalid'
);
return false;
}
Handle Edge Cases
// Check for undefined
if (data === undefined) return;
// Handle single values and arrays
const groups = typeof value === 'string' ? [value] : value;
Examples
1. Simple Validation
Task: Check if boolean value is valid
import { General, Types } from 'bc-minecraft-bedrock-types';
import { DiagnosticsBuilder, DiagnosticSeverity } from '../../types';
export function general_boolean_diagnose(
value: Types.OffsetWord,
diagnoser: DiagnosticsBuilder
): void {
if (General.Boolean.is(value.text)) return;
diagnoser.add(
value,
`Invalid boolean value: ${value.text}`,
DiagnosticSeverity.error,
'general.boolean.invalid'
);
}
2. Missing Resource Check
Task: Verify animation exists
export function diagnose_animation_implementation(
anim_id: string,
user: User,
diagnoser: WithMetadata<DiagnosticsBuilder, MolangMetadata>
): void {
const anim = diagnoser.context
.getProjectData()
.behaviors.animations.get(anim_id, diagnoser.project);
if (anim === undefined) {
return diagnoser.add(
user.id,
`Cannot find behaviors animations definition: ${anim_id}`,
DiagnosticSeverity.error,
'behaviorpack.animations.missing'
);
}
// Continue validation...
}
3. Component Validation
Task: Create reusable component checker
export function component_error<T>(
message: string,
code: string | number
): ComponentCheck<T> {
return (name, _component, _context, diagnoser) => {
diagnoser.add(name, message, DiagnosticSeverity.error, code);
};
}
// Usage
const checks: Record<string, ComponentCheck<Entity>> = {
'minecraft:is_tamed': component_error(
'This component requires rideable entities',
'behaviorpack.entity.component.is_tamed.invalid'
),
};
4. Deprecated Feature Warning
Task: Warn about deprecated properties
if (event.run_command) {
diagnoser.add(
`events/${event_id}`,
`Event uses deprecated run_command, use queue_command instead`,
DiagnosticSeverity.warning,
'behaviorpack.entity.event.run_command'
);
}
5. Complex Selector Validation
Task: Multiple validation checks with different error codes
export function minecraft_selector_diagnose(
pattern: ParameterInfo,
value: Types.OffsetWord,
diagnoser: DiagnosticsBuilder
) {
const sel = value.text;
// Validate selector syntax
if (sel.startsWith('@')) {
const selector = Minecraft.Selector.Selector.parse(sel, value.offset);
if (selector === undefined) {
diagnoser.add(
value,
'Invalid selector',
DiagnosticSeverity.error,
'minecraft.selector.invalid'
);
}
return;
}
// Handle fake entities
const name = Text.UnQuote(sel);
if (pattern.options?.allowFakePlayers === false) {
diagnoser.add(
value,
'No fake players / names allowed',
DiagnosticSeverity.error,
'minecraft.selector.invalid'
);
}
}
Common Utilities
Errors.missing()
Shorthand for missing resource errors:
import { Errors } from '../..';
const anim = diagnoser.context
.getProjectData()
.behaviors.animations.get(anim_id, diagnoser.project);
if (anim === undefined) {
// Generates code: "behaviorpack.animations.missing"
return Errors.missing('behaviors', 'animations', anim_id, diagnoser);
}
Component Helpers
For entity component validation:
import { component_error, component_warning } from '../../utility/components/checks';
const component_checks: Record<string, ComponentCheck<T>> = {
'minecraft:my_component': component_error(
'This component requires additional setup',
'behaviorpack.entity.component.my_component.invalid'
),
};
Testing
Test Checklist
- โ
Create test file in
packages/bedrock-diagnoser/test/ - โ Add valid and invalid test cases
- โ Verify diagnostic code matches
- โ Test edge cases (undefined, empty strings)
Example Test
import { TestDiagnoser } from '../../../../test/diagnoser';
import { diagnose } from '../src/diagnostics/your-diagnostic';
describe('Your Diagnostic', () => {
it('should report error for invalid value', () => {
const diagnoser = TestDiagnoser.create();
const value = { text: 'invalid', offset: 0 };
diagnose(value, diagnoser);
expect(diagnoser.hasCode('your.diagnostic.code')).toBe(true);
});
});
Resources
| Resource | Location |
|---|---|
| DiagnosticsBuilder Interface | packages/bedrock-diagnoser/src/types/diagnostics-builder.ts |
| Existing Examples | packages/bedrock-diagnoser/src/diagnostics/ |
| Error Utilities | packages/bedrock-diagnoser/src/diagnostics/errors/ |
| Contributing Guide | CONTRIBUTING.md |
Need Help?
- Check existing diagnostics in similar categories
- Review the Contributing Guide
- Open an issue for discussion
- Join community discussions
Happy Diagnosing! ๐