Skip to content

BMAD Module Issues.md

Saros Industries edited this page Jun 28, 2025 · 1 revision

BMAD Module Issues

BMAD Module Initialization Problems

BMAD Module Not Loading

Problem: BMAD module fails to initialize with the framework

Symptoms:

Error: BMAD module not found
Module 'bmad' is not registered
BMAD initialization failed

Solutions:

Check module registration

// framework.config.js - Ensure BMAD is enabled
module.exports = {
  modules: {
    bmad: {
      enabled: true,
      config: {
        database_prefix: 'bmad_',
        canvas_autosave: true,
        analytics_enabled: true
      }
    }
  }
};

Verify BMAD installation

# Check if BMAD module is installed
npm list @cursoriper/bmad
ls -la node_modules/@cursoriper/bmad/

# Reinstall BMAD module if missing
npm install @cursoriper/bmad@latest

# Verify module structure
cat node_modules/@cursoriper/bmad/package.json

Manual module registration

// src/app.js - Manual BMAD registration
const { Framework } = require('@cursoriper/core');
const BMADModule = require('@cursoriper/bmad');

const framework = new Framework();

// Register BMAD module manually
framework.registerModule('bmad', BMADModule, {
  database_prefix: 'bmad_',
  canvas_autosave: true
});

framework.start();

BMAD Database Schema Issues

Problem: BMAD database tables not created or corrupted

Symptoms:

Table 'bmad_business_models' doesn't exist
Column 'canvas_data' not found
Foreign key constraint fails

Solutions:

Force schema recreation

# Run BMAD database migration
npm run bmad:migrate

# Or use framework CLI
npx @cursoriper/cli bmad:db:reset

Manual schema creation

-- Create BMAD tables manually
CREATE TABLE IF NOT EXISTS bmad_business_models (
    id VARCHAR(36) PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    description TEXT,
    canvas_data JSON,
    status VARCHAR(50) DEFAULT 'draft',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    created_by VARCHAR(36),
    organization_id VARCHAR(36)
);

CREATE TABLE IF NOT EXISTS bmad_stakeholders (
    id VARCHAR(36) PRIMARY KEY,
    business_model_id VARCHAR(36),
    name VARCHAR(255) NOT NULL,
    type VARCHAR(100),
    influence_level INT DEFAULT 1,
    engagement_level INT DEFAULT 1,
    contact_info JSON,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (business_model_id) REFERENCES bmad_business_models(id) ON DELETE CASCADE
);

CREATE TABLE IF NOT EXISTS bmad_canvases (
    id VARCHAR(36) PRIMARY KEY,
    business_model_id VARCHAR(36),
    canvas_type VARCHAR(50) DEFAULT 'standard',
    sections JSON,
    version VARCHAR(20) DEFAULT '1.0.0',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (business_model_id) REFERENCES bmad_business_models(id) ON DELETE CASCADE
);

Check database permissions

// Test BMAD database access
const { Framework } = require('@cursoriper/core');

async function testBMADDatabase() {
  const framework = new Framework();
  await framework.initialize();
  
  const bmadService = framework.getService('bmad');
  
  try {
    // Test database connection
    const models = await bmadService.getBusinessModels();
    console.log('βœ“ BMAD database accessible');
    console.log(`Found ${models.length} business models`);
  } catch (error) {
    console.error('βœ— BMAD database error:', error.message);
    
    // Check specific table access
    const db = framework.getDatabase();
    try {
      await db.query('SELECT 1 FROM bmad_business_models LIMIT 1');
      console.log('βœ“ bmad_business_models table accessible');
    } catch (tableError) {
      console.error('βœ— bmad_business_models table error:', tableError.message);
    }
  }
}

testBMADDatabase();

Business Model Canvas Issues

Canvas Data Corruption

Problem: Business model canvas data becomes corrupted or invalid

Symptoms:

Error parsing canvas JSON data
Invalid canvas structure
Canvas sections missing
Null reference exception in canvas

Solutions:

Validate canvas data structure

// Canvas validation utility
class CanvasValidator {
  static validateCanvas(canvasData) {
    const requiredSections = [
      'value_propositions',
      'customer_segments',
      'channels',
      'customer_relationships',
      'revenue_streams',
      'key_resources',
      'key_activities',
      'key_partnerships',
      'cost_structure'
    ];

    const errors = [];
    
    // Check if canvas data exists
    if (!canvasData || typeof canvasData !== 'object') {
      errors.push('Canvas data is missing or invalid');
      return { valid: false, errors };
    }

    // Check required sections
    requiredSections.forEach(section => {
      if (!canvasData[section]) {
        errors.push(`Missing required section: ${section}`);
      } else if (!Array.isArray(canvasData[section])) {
        errors.push(`Section ${section} must be an array`);
      }
    });

    // Validate section content
    Object.entries(canvasData).forEach(([section, items]) => {
      if (Array.isArray(items)) {
        items.forEach((item, index) => {
          if (!item.id || !item.text) {
            errors.push(`Invalid item at ${section}[${index}]: missing id or text`);
          }
        });
      }
    });

    return {
      valid: errors.length === 0,
      errors
    };
  }

  static sanitizeCanvas(canvasData) {
    const requiredSections = [
      'value_propositions',
      'customer_segments',
      'channels',
      'customer_relationships',
      'revenue_streams',
      'key_resources',
      'key_activities',
      'key_partnerships',
      'cost_structure'
    ];

    const sanitized = {};

    requiredSections.forEach(section => {
      sanitized[section] = [];
      
      if (canvasData[section] && Array.isArray(canvasData[section])) {
        sanitized[section] = canvasData[section]
          .filter(item => item && typeof item === 'object')
          .map(item => ({
            id: item.id || this.generateId(),
            text: String(item.text || ''),
            description: String(item.description || ''),
            validated: Boolean(item.validated),
            created_at: item.created_at || new Date().toISOString()
          }));
      }
    });

    return sanitized;
  }

  static generateId() {
    return 'item_' + Math.random().toString(36).substr(2, 9);
  }
}

// Usage
const bmadService = framework.getService('bmad');

async function repairCanvasData(businessModelId) {
  try {
    const model = await bmadService.getBusinessModel(businessModelId);
    
    // Validate current canvas
    const validation = CanvasValidator.validateCanvas(model.canvas_data);
    
    if (!validation.valid) {
      console.log('Canvas validation errors:', validation.errors);
      
      // Sanitize and repair
      const sanitized = CanvasValidator.sanitizeCanvas(model.canvas_data || {});
      
      // Update model with sanitized data
      await bmadService.updateBusinessModel(businessModelId, {
        canvas_data: sanitized
      });
      
      console.log('Canvas data repaired successfully');
    }
  } catch (error) {
    console.error('Canvas repair failed:', error);
  }
}

Canvas Auto-save Failures

Problem: Canvas changes not being saved automatically

Symptoms:

Canvas changes lost after refresh
Auto-save indicator stuck
"Save failed" errors

Solutions:

Check auto-save configuration

// framework.config.js
module.exports = {
  modules: {
    bmad: {
      enabled: true,
      config: {
        canvas_autosave: true,
        autosave_interval: 5000, // 5 seconds
        max_retries: 3,
        retry_delay: 1000
      }
    }
  }
};

Implement robust auto-save

// Enhanced auto-save with error handling
class CanvasAutoSave {
  constructor(bmadService, options = {}) {
    this.bmadService = bmadService;
    this.options = {
      interval: options.interval || 5000,
      maxRetries: options.maxRetries || 3,
      retryDelay: options.retryDelay || 1000,
      ...options
    };
    
    this.pendingChanges = new Map();
    this.saveTimers = new Map();
  }

  scheduleAutoSave(modelId, canvasData) {
    // Store pending changes
    this.pendingChanges.set(modelId, canvasData);
    
    // Clear existing timer
    if (this.saveTimers.has(modelId)) {
      clearTimeout(this.saveTimers.get(modelId));
    }
    
    // Schedule new save
    const timer = setTimeout(() => {
      this.performAutoSave(modelId);
    }, this.options.interval);
    
    this.saveTimers.set(modelId, timer);
  }

  async performAutoSave(modelId, retryCount = 0) {
    try {
      const canvasData = this.pendingChanges.get(modelId);
      if (!canvasData) return;

      // Validate before saving
      const validation = CanvasValidator.validateCanvas(canvasData);
      if (!validation.valid) {
        console.warn('Skipping auto-save due to validation errors:', validation.errors);
        return;
      }

      // Perform save
      await this.bmadService.updateBusinessModel(modelId, {
        canvas_data: canvasData,
        updated_at: new Date()
      });

      // Clear pending changes
      this.pendingChanges.delete(modelId);
      this.saveTimers.delete(modelId);
      
      console.log(`Auto-save successful for model ${modelId}`);
      
    } catch (error) {
      console.error(`Auto-save failed for model ${modelId}:`, error);
      
      // Retry if attempts remaining
      if (retryCount < this.options.maxRetries) {
        setTimeout(() => {
          this.performAutoSave(modelId, retryCount + 1);
        }, this.options.retryDelay * (retryCount + 1));
      } else {
        console.error(`Auto-save failed permanently for model ${modelId}`);
        // Notify user of save failure
        this.notifyUser(modelId, 'Auto-save failed. Please save manually.');
      }
    }
  }

  notifyUser(modelId, message) {
    // Emit event for UI to handle
    const framework = require('@cursoriper/core').getInstance();
    framework.events.emit('bmad.autosave.failed', {
      modelId,
      message,
      timestamp: new Date()
    });
  }
}

Stakeholder Management Issues

Stakeholder Data Inconsistencies

Problem: Stakeholder information not syncing properly

Symptoms:

Stakeholder roles inconsistent
Duplicate stakeholder entries
Orphaned stakeholder records

Solutions:

Stakeholder data cleanup

async function cleanupStakeholderData() {
  const bmadService = framework.getService('bmad');
  const db = framework.getDatabase();
  
  try {
    // Find orphaned stakeholders
    const orphanedStakeholders = await db.query(`
      SELECT s.id, s.name, s.business_model_id
      FROM bmad_stakeholders s
      LEFT JOIN bmad_business_models bm ON s.business_model_id = bm.id
      WHERE bm.id IS NULL
    `);
    
    console.log(`Found ${orphanedStakeholders.length} orphaned stakeholders`);
    
    // Remove orphaned records
    for (const stakeholder of orphanedStakeholders) {
      await db.query('DELETE FROM bmad_stakeholders WHERE id = ?', [stakeholder.id]);
      console.log(`Removed orphaned stakeholder: ${stakeholder.name}`);
    }
    
    // Find duplicate stakeholders
    const duplicates = await db.query(`
      SELECT business_model_id, name, COUNT(*) as count
      FROM bmad_stakeholders
      GROUP BY business_model_id, name
      HAVING COUNT(*) > 1
    `);
    
    console.log(`Found ${duplicates.length} duplicate stakeholder groups`);
    
    // Merge duplicates
    for (const duplicate of duplicates) {
      await mergeStakeholderDuplicates(duplicate.business_model_id, duplicate.name);
    }
    
    console.log('Stakeholder cleanup completed');
    
  } catch (error) {
    console.error('Stakeholder cleanup failed:', error);
  }
}

async function mergeStakeholderDuplicates(businessModelId, stakeholderName) {
  const db = framework.getDatabase();
  
  // Get all duplicates
  const duplicates = await db.query(`
    SELECT * FROM bmad_stakeholders
    WHERE business_model_id = ? AND name = ?
    ORDER BY created_at ASC
  `, [businessModelId, stakeholderName]);
  
  if (duplicates.length <= 1) return;
  
  // Keep the first one, merge data from others
  const primary = duplicates[0];
  const toMerge = duplicates.slice(1);
  
  // Merge contact info and other data
  const mergedContactInfo = {};
  const mergedData = {
    type: primary.type,
    influence_level: primary.influence_level,
    engagement_level: primary.engagement_level
  };
  
  toMerge.forEach(stakeholder => {
    // Merge contact info
    if (stakeholder.contact_info) {
      Object.assign(mergedContactInfo, JSON.parse(stakeholder.contact_info));
    }
    
    // Take highest influence/engagement levels
    mergedData.influence_level = Math.max(mergedData.influence_level, stakeholder.influence_level);
    mergedData.engagement_level = Math.max(mergedData.engagement_level, stakeholder.engagement_level);
  });
  
  // Update primary record
  await db.query(`
    UPDATE bmad_stakeholders
    SET contact_info = ?, influence_level = ?, engagement_level = ?, updated_at = NOW()
    WHERE id = ?
  `, [
    JSON.stringify({ ...JSON.parse(primary.contact_info || '{}'), ...mergedContactInfo }),
    mergedData.influence_level,
    mergedData.engagement_level,
    primary.id
  ]);
  
  // Delete duplicate records
  for (const duplicate of toMerge) {
    await db.query('DELETE FROM bmad_stakeholders WHERE id = ?', [duplicate.id]);
  }
  
  console.log(`Merged ${toMerge.length} duplicate stakeholders for: ${stakeholderName}`);
}

Analytics and Reporting Issues

Analytics Data Not Generating

Problem: BMAD analytics reports are empty or not updating

Symptoms:

Analytics dashboard shows no data
Reports generation fails
"No data available" messages

Solutions:

Check analytics configuration

// framework.config.js
module.exports = {
  modules: {
    bmad: {
      enabled: true,
      config: {
        analytics_enabled: true,
        analytics_schedule: '0 2 * * *', // Daily at 2 AM
        metrics_retention_days: 90,
        real_time_analytics: true
      }
    }
  }
};

Force analytics regeneration

async function regenerateAnalytics() {
  const bmadService = framework.getService('bmad');
  
  try {
    // Get all business models
    const models = await bmadService.getBusinessModels();
    
    for (const model of models) {
      console.log(`Generating analytics for model: ${model.name}`);
      
      // Generate model analytics
      const analytics = await bmadService.generateModelAnalytics(model.id);
      console.log(`Generated ${analytics.metrics.length} metrics`);
      
      // Generate stakeholder analytics
      const stakeholderAnalytics = await bmadService.generateStakeholderAnalytics(model.id);
      console.log(`Generated stakeholder analytics with ${stakeholderAnalytics.engagement_scores.length} scores`);
    }
    
    // Generate portfolio analytics
    const portfolioAnalytics = await bmadService.generatePortfolioAnalytics();
    console.log('Portfolio analytics generated successfully');
    
  } catch (error) {
    console.error('Analytics regeneration failed:', error);
  }
}

Manual analytics calculation

class BMADAnalyticsCalculator {
  constructor(bmadService) {
    this.bmadService = bmadService;
  }

  async calculateModelCompleteness(modelId) {
    const model = await this.bmadService.getBusinessModel(modelId);
    const canvas = model.canvas_data || {};
    
    const requiredSections = [
      'value_propositions',
      'customer_segments',
      'channels',
      'customer_relationships',
      'revenue_streams',
      'key_resources',
      'key_activities',
      'key_partnerships',
      'cost_structure'
    ];

    let completedSections = 0;
    let totalItems = 0;
    let completedItems = 0;

    requiredSections.forEach(section => {
      if (canvas[section] && Array.isArray(canvas[section]) && canvas[section].length > 0) {
        completedSections++;
        totalItems += canvas[section].length;
        completedItems += canvas[section].filter(item => item.validated).length;
      }
    });

    return {
      section_completeness: completedSections / requiredSections.length,
      item_completeness: totalItems > 0 ? completedItems / totalItems : 0,
      total_sections: requiredSections.length,
      completed_sections: completedSections,
      total_items: totalItems,
      completed_items: completedItems
    };
  }

  async calculateStakeholderEngagement(modelId) {
    const stakeholders = await this.bmadService.getStakeholders(modelId);
    
    if (stakeholders.length === 0) {
      return { average_engagement: 0, total_stakeholders: 0 };
    }

    const totalEngagement = stakeholders.reduce((sum, stakeholder) => 
      sum + (stakeholder.engagement_level || 0), 0);
    
    const averageEngagement = totalEngagement / stakeholders.length;
    
    const engagementDistribution = {
      low: stakeholders.filter(s => (s.engagement_level || 0) <= 2).length,
      medium: stakeholders.filter(s => (s.engagement_level || 0) > 2 && (s.engagement_level || 0) <= 4).length,
      high: stakeholders.filter(s => (s.engagement_level || 0) > 4).length
    };

    return {
      average_engagement: averageEngagement,
      total_stakeholders: stakeholders.length,
      engagement_distribution: engagementDistribution
    };
  }
}

Performance Optimization

BMAD Query Performance Issues

Problem: BMAD operations are slow or timing out

Symptoms:

Business model loading takes too long
Canvas save operations timeout
Stakeholder queries are slow

Solutions:

Add database indexes

-- Optimize BMAD queries with indexes
CREATE INDEX idx_bmad_models_status ON bmad_business_models(status);
CREATE INDEX idx_bmad_models_created_by ON bmad_business_models(created_by);
CREATE INDEX idx_bmad_models_organization ON bmad_business_models(organization_id);
CREATE INDEX idx_bmad_models_updated ON bmad_business_models(updated_at);

CREATE INDEX idx_bmad_stakeholders_model ON bmad_stakeholders(business_model_id);
CREATE INDEX idx_bmad_stakeholders_type ON bmad_stakeholders(type);
CREATE INDEX idx_bmad_stakeholders_influence ON bmad_stakeholders(influence_level);

CREATE INDEX idx_bmad_canvases_model ON bmad_canvases(business_model_id);
CREATE INDEX idx_bmad_canvases_type ON bmad_canvases(canvas_type);
CREATE INDEX idx_bmad_canvases_updated ON bmad_canvases(updated_at);

Implement query optimization

class OptimizedBMADService {
  constructor(framework) {
    this.db = framework.getDatabase();
    this.cache = framework.getCache();
  }

  async getBusinessModel(modelId) {
    // Check cache first
    const cacheKey = `bmad:model:${modelId}`;
    let model = await this.cache.get(cacheKey);
    
    if (!model) {
      // Fetch from database
      model = await this.db.query(`
        SELECT bm.*, 
               COUNT(s.id) as stakeholder_count,
               MAX(s.updated_at) as last_stakeholder_update
        FROM bmad_business_models bm
        LEFT JOIN bmad_stakeholders s ON bm.id = s.business_model_id
        WHERE bm.id = ?
        GROUP BY bm.id
      `, [modelId]);
      
      if (model.length > 0) {
        model = model[0];
        // Cache for 5 minutes
        await this.cache.set(cacheKey, model, 300);
      }
    }
    
    return model;
  }

  async getBusinessModels(filters = {}) {
    // Build optimized query
    let query = `
      SELECT bm.id, bm.name, bm.description, bm.status, bm.created_at, bm.updated_at,
             COUNT(s.id) as stakeholder_count,
             CASE 
               WHEN bm.canvas_data IS NOT NULL AND JSON_LENGTH(bm.canvas_data) > 0 
               THEN 'complete' 
               ELSE 'incomplete' 
             END as canvas_status
      FROM bmad_business_models bm
      LEFT JOIN bmad_stakeholders s ON bm.id = s.business_model_id
    `;
    
    const conditions = [];
    const params = [];
    
    if (filters.status) {
      conditions.push('bm.status = ?');
      params.push(filters.status);
    }
    
    if (filters.organization_id) {
      conditions.push('bm.organization_id = ?');
      params.push(filters.organization_id);
    }
    
    if (filters.created_after) {
      conditions.push('bm.created_at > ?');
      params.push(filters.created_after);
    }
    
    if (conditions.length > 0) {
      query += ' WHERE ' + conditions.join(' AND ');
    }
    
    query += ' GROUP BY bm.id ORDER BY bm.updated_at DESC';
    
    if (filters.limit) {
      query += ` LIMIT ${parseInt(filters.limit)}`;
    }
    
    return await this.db.query(query, params);
  }

  async invalidateCache(modelId) {
    // Invalidate related cache entries
    const keys = [
      `bmad:model:${modelId}`,
      `bmad:stakeholders:${modelId}`,
      `bmad:canvas:${modelId}`,
      `bmad:analytics:${modelId}`
    ];
    
    await Promise.all(keys.map(key => this.cache.delete(key)));
  }
}

Last Updated: June 28, 2025
Framework Version: CursorRIPER.sigma v1.0+
BMAD Module Version: 2.1.0

πŸš€ Getting Started


🧠 Core Concepts


⚑ Features


πŸ“– Guides


πŸ“‹ Reference


πŸ”Œ Advanced

MCP Integration

BMAD Enterprise


πŸ”§ Troubleshooting

Quick Navigation

🚨 Emergency Procedures

πŸ“‹ Common Issues

Installation & Setup

  • Installation Issues
    • Node.js Version Compatibility
    • Package Installation Failures
    • Framework Dependencies Missing
    • Database Connection Issues
    • Port Conflicts
    • Environment Setup Issues
    • Build and Development Issues
    • Framework CLI Issues

Configuration & Runtime

  • Configuration & Runtime Issues
    • Framework Configuration Problems
    • Runtime Performance Issues
    • Module Loading and Plugin Issues
    • Database and Storage Issues
    • Memory Leaks and High Memory Usage
    • High CPU Usage

BMAD Module

  • BMAD Module Issues
    • BMAD Module Initialization Problems
    • Business Model Canvas Issues
    • Stakeholder Management Issues
    • Analytics and Reporting Issues
    • Performance Optimization

Database & API

  • Database & API Issues
    • Database Connection Problems
    • Database Migration Issues
    • API Performance and Reliability Issues
    • Data Consistency Issues
    • Transaction Problems

Performance & Memory

Security & Authentication

  • Security & Authentication Issues
    • Authentication Failures
    • Authorization Problems
    • JWT Token Issues
    • Session Management
    • CORS and Security Headers
    • SSL/TLS Configuration

Deployment & Production

  • Deployment & Production Issues
    • Production Deployment Failures
    • Environment Configuration
    • Load Balancing Issues
    • Monitoring and Logging
    • Backup and Recovery

Information to Gather

When reporting issues, please include:

  • Framework version (npm list @cursoriper/core)
  • Node.js version (node --version)
  • Operating system and version
  • Error messages and stack traces
  • Steps to reproduce the issue
  • Configuration files (sanitized)
  • Recent changes or deployments

Tech Docs & Suport


πŸ“ž Support & Community


πŸ“‹ Release Notes

Last Updated: June 28, 2025
Framework Version: CursorRIPER.sigma v1.0+

For the original verbose framework, see CursorRIPER

← Back to Home

Clone this wiki locally