Troubleshooting

Common issues, error messages, and solutions for JSCAD development

Common Errors

Frequently encountered error messages and their solutions.

"No main() function defined"

Error Message:

No main() function defined. Please ensure your code exports a main() function.

Solution:

// ❌ Missing main function
const { cube } = jscad.primitives;
return cube({ size: 10 });

// ✅ Correct implementation
function main() {
  const { cube } = jscad.primitives;
  return cube({ size: 10 });
}

"JSCAD not initialized"

Error Message:

JSCAD not initialized

Solution:

// ❌ Direct require (not supported)
const jscad = require('@jscad/modeling');

// ✅ Use global jscad object
const { cube } = jscad.primitives;
const { translate } = jscad.transforms;

"Invalid geometry"

Error Message:

Invalid JSCAD geometry

Solution:

// ❌ Returning invalid geometry
function main() {
  return { invalid: 'geometry' };
}

// ✅ Return valid JSCAD primitives
function main() {
  const { cube, sphere } = jscad.primitives;
  return cube({ size: 10 });
}

"No valid geometry objects generated"

Error Message:

No valid geometry objects generated. Please check that your main() function returns valid JSCAD geometry

Solution:

// ❌ Returning undefined or null
function main() {
  if (someCondition) {
    return cube({ size: 10 });
  }
  // Missing return statement
}

// ✅ Always return valid geometry
function main() {
  if (someCondition) {
    return cube({ size: 10 });
  }
  return sphere({ radius: 5 }); // Fallback geometry
}

Performance Issues

Common performance problems and optimization strategies.

Slow Compilation

Symptoms: Long compilation times, browser freezing

Solutions:

// ❌ Creating many individual objects
function main() {
  const objects = [];
  for (let i = 0; i < 1000; i++) {
    objects.push(cube({ size: 1 }));
  }
  return objects;
}

// ✅ Use union for better performance
function main() {
  const { union } = jscad.booleans;
  const { cube } = jscad.primitives;
  const { translate } = jscad.transforms;
  
  const baseCube = cube({ size: 1 });
  const instances = [];
  
  for (let i = 0; i < 1000; i++) {
    instances.push(translate([i, 0, 0], baseCube));
  }
  
  return union(instances);
}

High Memory Usage

Symptoms: Browser crashes, slow rendering

Solutions:

// ❌ High resolution for simple shapes
function main() {
  return sphere({ radius: 5, segments: 128 });
}

// ✅ Use appropriate resolution
function main() {
  return sphere({ radius: 5, segments: 32 });
}

// ❌ Unnecessary complex operations
function main() {
  const complex = union(sphere({ radius: 5 }), cube({ size: 10 }));
  return complex; // May be unnecessary
}

// ✅ Simplify when possible
function main() {
  return cube({ size: 10 }); // Simpler and faster
}

Boolean Operation Issues

Common problems with Boolean operations and their solutions.

Non-Manifold Geometry

Symptoms: Boolean operations fail, invalid results

Solutions:

// ❌ Overlapping faces
function main() {
  const { cube } = jscad.primitives;
  const { union } = jscad.booleans;
  
  const cube1 = cube({ size: 10 });
  const cube2 = cube({ size: 10 }); // Same position
  
  return union(cube1, cube2); // Creates non-manifold geometry
}

// ✅ Ensure proper separation or overlap
function main() {
  const { cube } = jscad.primitives;
  const { translate } = jscad.transforms;
  const { union } = jscad.booleans;
  
  const cube1 = cube({ size: 10 });
  const cube2 = translate([5, 0, 0], cube({ size: 10 }));
  
  return union(cube1, cube2);
}

Open Geometry

Symptoms: Boolean operations produce unexpected results

Solutions:

// ❌ Open geometry (missing faces)
function main() {
  const { cube } = jscad.primitives;
  const { subtract } = jscad.booleans;
  
  const outer = cube({ size: 10 });
  const inner = cube({ size: 8 });
  
  return subtract(outer, inner); // May create open geometry
}

// ✅ Ensure watertight geometry
function main() {
  const { cube } = jscad.primitives;
  const { subtract } = jscad.booleans;
  const { translate } = jscad.transforms;
  
  const outer = cube({ size: 10 });
  const inner = translate([0, 0, 1], cube({ size: 8 }));
  
  return subtract(outer, inner); // Better overlap
}

Parameter Issues

Common problems with parameter definitions and usage.

Invalid Parameter Types

Symptoms: Parameters not working, unexpected values

Solutions:

// ❌ Invalid parameter definition
function getParameterDefinitions() {
  return [
    { name: 'size', type: 'number', initial: 10 } // Invalid type
  ];
}

// ✅ Valid parameter types
function getParameterDefinitions() {
  return [
    { name: 'size', type: 'float', initial: 10, min: 1, max: 50 },
    { name: 'segments', type: 'int', initial: 32, min: 8, max: 64 },
    { name: 'enabled', type: 'boolean', initial: true },
    { name: 'shape', type: 'choice', choices: ['cube', 'sphere'], initial: 'cube' }
  ];
}

Missing Parameter Validation

Symptoms: Crashes with certain parameter values

Solutions:

// ❌ No validation
function main(params) {
  const { sphere } = jscad.primitives;
  return sphere({ radius: params.radius });
}

// ✅ Add validation
function main(params) {
  const { sphere } = jscad.primitives;
  
  // Validate parameters
  const radius = Math.max(0.1, params.radius || 5);
  const segments = Math.max(8, Math.min(64, params.segments || 32));
  
  return sphere({ radius, segments });
}

Debugging Techniques

Effective strategies for debugging JSCAD code.

Console Logging

function main(params) {
  console.log('Parameters:', params);
  
  const { cube } = jscad.primitives;
  const result = cube({ size: params.size || 10 });
  
  console.log('Result:', result);
  return result;
}

Step-by-Step Testing

function main(params) {
  // Test 1: Basic primitive
  const basic = cube({ size: 10 });
  console.log('Basic cube:', basic);
  
  // Test 2: Transformation
  const transformed = translate([5, 0, 0], basic);
  console.log('Transformed:', transformed);
  
  // Test 3: Boolean operation
  const combined = union(basic, transformed);
  console.log('Combined:', combined);
  
  return combined;
}

Parameter Testing

function main(params) {
  // Test with different parameter values
  const testCases = [
    { size: 5, segments: 8 },
    { size: 10, segments: 16 },
    { size: 20, segments: 32 }
  ];
  
  // Use the first test case for now
  const testParams = testCases[0];
  console.log('Testing with:', testParams);
  
  const { sphere } = jscad.primitives;
  return sphere({ 
    radius: testParams.size / 2, 
    segments: testParams.segments 
  });
}

Best Practices

Guidelines to prevent common issues and improve code quality.

Code Organization

  • • Always define a main() function
  • • Use descriptive parameter names
  • • Add comments for complex operations
  • • Validate parameters before use
  • • Test with different parameter values

Performance Guidelines

  • • Use appropriate primitive resolution
  • • Combine objects with union when possible
  • • Avoid unnecessary transformations
  • • Cache frequently used geometries
  • • Use conditional logic for complex operations

Error Prevention

  • • Always return valid geometry from main()
  • • Handle edge cases in parameter validation
  • • Test Boolean operations with simple shapes first
  • • Use try-catch for complex operations
  • • Provide fallback values for parameters

🔧 Quick Fixes

• Always define main() function

• Use jscad global object

• Return valid geometry

• Validate parameters

• Test with simple shapes first