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

  1. Choose error code location based on type (behavior pack, resource pack, general, minecraft-specific)
  2. Follow naming convention: category.subcategory.type.detail
  3. Use diagnoser.add() with position, message, severity, and code
  4. 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

InterfacePurpose
DiagnosticsBuilderMain interface with add() method for adding diagnostics
DocumentDiagnosticsBuilderExtension for document-specific diagnostics
DiagnosticSeveritySeverity 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

CategoryUse For
behaviorpackBehavior pack issues
resourcepackResource pack issues
generalGeneric validation (types, formats)
minecraftMinecraft concepts (selectors, effects, tags)
jsonJSON parsing/validation
diagnosticsInternal system issues

Common Type Suffixes

SuffixMeaning
.missingResource/definition not found
.invalidInvalid syntax or value
.deprecatedDeprecated feature
.minimum / .maximumValue range violation
.duplicateDuplicate 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:

TypeDirectory
Behavior packdiagnostics/behavior-pack/
Resource packdiagnostics/resource-pack/
General validationdiagnostics/general/
Minecraft-specificdiagnostics/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

  1. Create test file with problematic code
  2. Run diagnostic system
  3. Verify error reported correctly
  4. 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

PracticeExample
Use consistent codesFollow category.subcategory.type pattern
Be specificInclude problematic value in message
Be conciseKeep messages short and clear
Suggest fixesTell user how to resolve the issue
Reuse functionsUse existing utilities like Errors.missing()

โŒ Don'ts

Anti-patternWhy
Vague messages"Error" tells user nothing
Generic codes"error" doesn't categorize
Missing contextUser can't identify the problem
Overly long messagesHard 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

  1. โœ… Create test file in packages/bedrock-diagnoser/test/
  2. โœ… Add valid and invalid test cases
  3. โœ… Verify diagnostic code matches
  4. โœ… 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

ResourceLocation
DiagnosticsBuilder Interfacepackages/bedrock-diagnoser/src/types/diagnostics-builder.ts
Existing Examplespackages/bedrock-diagnoser/src/diagnostics/
Error Utilitiespackages/bedrock-diagnoser/src/diagnostics/errors/
Contributing GuideCONTRIBUTING.md

Need Help?

  1. Check existing diagnostics in similar categories
  2. Review the Contributing Guide
  3. Open an issue for discussion
  4. Join community discussions

Happy Diagnosing! ๐Ÿ”