Skip to content

Troubleshooting

This guide covers common issues you might encounter when working with YAPL and how to resolve them.

Error:

npm ERR! 404 Not Found - GET https://registry.npmjs.org/yapl

Solution: Use the correct package name:

Terminal window
npm install @yapl-language/yapl.ts

Error:

Cannot find module 'yapl' or its corresponding type declarations

Solution: Use the correct import:

import { NodeYAPL } from "@yapl-language/yapl.ts";

Error:

ENOENT: no such file or directory, open '/path/to/base/system'

Problem:

{% extends "base/system" %}

Solution: Always include file extensions:

{% extends "base/system.md.yapl" %}

Error:

Template parsing error: Missing {% endif %}

Problem:

{% if condition %}
Content here
{# Missing {% endif %} #}

Solution: Ensure all control structures are properly closed:

{% if condition %}
Content here
{% endif %}

Error:

Template parsing error: Invalid block name

Problem:

{% block 123invalid %}
Content
{% endblock %}

Solution: Use valid block names (letters, numbers, underscores, hyphens, colons):

{% block valid_block_name %}
Content
{% endblock %}

Error:

Error: Path escapes baseDir: ../../../etc/passwd

Cause: Attempting to access files outside the configured baseDir with strictPaths: true.

Solutions:

  1. Use relative paths within baseDir:
{% extends "../base/system.md.yapl" %} {# OK if within baseDir #}
  1. Disable strict paths (not recommended for production):
const yapl = new NodeYAPL({
baseDir: "./prompts",
strictPaths: false,
});
  1. Adjust your baseDir:
const yapl = new NodeYAPL({
baseDir: "./parent-directory", // Set higher in directory tree
strictPaths: true,
});

Error:

Error: Max template depth exceeded (possible recursion).

Cause: Circular dependencies or deeply nested templates.

Common Causes:

  1. Circular includes:
{# template1.yapl #}
{% include "template2.yapl" %}
{# template2.yapl #}
{% include "template1.yapl" %} {# Circular! #}
  1. Self-referencing templates:
{# template.yapl #}
{% include "template.yapl" %} {# Self-reference! #}

Solutions:

  1. Check for circular dependencies
  2. Increase maxDepth if legitimately needed:
const yapl = new NodeYAPL({
baseDir: "./prompts",
maxDepth: 50, // Default is 20
});

Error:

Error: For loop iterable must be an array, got: string

Problem:

{% for char in "hello" %} {# String, not array #}
{{ char }}
{% endfor %}

Solution: Ensure you’re iterating over arrays:

{% for item in items %} {# items must be an array #}
{{ item }}
{% endfor %}

Or convert strings to arrays in your data:

const data = {
characters: "hello".split(""), // ["h", "e", "l", "l", "o"]
};

Error:

ENOENT: no such file or directory, open '/path/to/template.yapl'

Debugging Steps:

  1. Check file exists:
Terminal window
ls -la /path/to/template.yapl
  1. Verify baseDir configuration:
console.log("Base directory:", yapl.baseDir);
  1. Check file permissions:
Terminal window
ls -la /path/to/
  1. Use absolute paths for debugging:
const yapl = new NodeYAPL({
baseDir: path.resolve("./prompts"), // Absolute path
});

Error:

EACCES: permission denied, open '/path/to/template.yapl'

Solutions:

  1. Check file permissions:
Terminal window
chmod 644 /path/to/template.yapl
  1. Check directory permissions:
Terminal window
chmod 755 /path/to/directory
  1. Run with appropriate user permissions

Problem: Variables showing as empty in output.

Debugging:

const result = await yapl.renderString("{{ missing_var }}", {});
console.log(result.content); // Empty string

Solutions:

  1. Use default values:
{{ missing_var | default("fallback value") }}
  1. Check variable names:
const data = {
userName: "Alice", // camelCase
};
// This won't work:
// {{ user_name }}
// This will work:
// {{ userName }}
  1. Debug variable access:
{# Debug output #}
Available variables: {{ . }}
User name: {{ user.name }}

Problem:

{{ user.profile.email }} {# Returns empty #}

Debugging:

const data = {
user: {
profile: {
email: "alice@example.com",
},
},
};
// Check data structure
console.log(JSON.stringify(data, null, 2));

Common Issues:

  1. Null/undefined in chain:
const data = {
user: null, // This breaks user.profile.email
};
  1. Typos in property names:
const data = {
user: {
profil: {
// Typo: should be "profile"
email: "alice@example.com",
},
},
};

Error:

Error: File loading is not available. Provide a loadFile function in YAPLOptions or use renderString for browser usage.

Problem:

import { YAPL } from "@yapl-language/yapl.ts";
const yapl = new YAPL({ baseDir: "/templates" });
await yapl.render("template.yapl"); // Error!

Solution: Use renderString in browsers:

import { YAPL } from "@yapl-language/yapl.ts";
const yapl = new YAPL({ baseDir: "/templates" });
const templateContent = await fetch("/templates/template.yapl").then((r) =>
r.text()
);
const result = await yapl.renderString(templateContent, variables);

Or provide custom file loading:

const yapl = new YAPL({
baseDir: "/templates",
loadFile: async (path) => {
const response = await fetch(path);
return response.text();
},
resolvePath: (templateRef, fromDir, ensureExt) => {
return new URL(ensureExt(templateRef), fromDir).href;
},
});

Symptoms:

  • Long render times
  • High memory usage
  • Timeouts

Debugging:

  1. Enable caching:
const yapl = new NodeYAPL({
baseDir: "./prompts",
cache: true, // Enable file caching
});
  1. Profile template complexity:
console.time("render");
const result = await yapl.render("complex-template.yapl", data);
console.timeEnd("render");
  1. Check template depth:
console.log("Used files:", result.usedFiles.length);

Solutions:

  1. Reduce template nesting
  2. Simplify complex conditionals
  3. Break large templates into smaller pieces
  4. Pre-process complex data structures

Symptoms:

  • Increasing memory usage over time
  • Out of memory errors

Solutions:

  1. Disable caching for development:
const yapl = new NodeYAPL({
baseDir: "./prompts",
cache: false, // Disable for development
});
  1. Create new instances periodically:
// For long-running processes
let yapl = new NodeYAPL(options);
setInterval(() => {
yapl = new NodeYAPL(options); // Fresh instance
}, 1000 * 60 * 60); // Every hour
// Add debug output to templates
const debugTemplate = `
{# Debug info #}
Variables: {{ . }}
User: {{ user }}
Config: {{ config }}
{# Original template #}
${originalTemplate}
`;
const result = await yapl.renderString(template, variables);
// Show exact output with whitespace
console.log("Content:", JSON.stringify(result.content));
// Show used files
console.log("Used files:", result.usedFiles);
// Test individual components
const componentResult = await yapl.renderString(
'{% include "components/header.yapl" %}',
testData
);
// Check data before rendering
function validateData(data) {
console.log("Data structure:");
console.log(JSON.stringify(data, null, 2));
// Check for common issues
if (data.user && !data.user.name) {
console.warn("Warning: user.name is missing");
}
}
validateData(templateData);
const result = await yapl.render("template.yapl", templateData);
  1. Syntax Reference - Complete syntax guide
  2. API Reference - Full API
  • GitHub Issues: Report bugs and request features
  • Discord Community: Get help from other users
  • Stack Overflow: Search for yapl tag

When reporting issues, include:

  1. YAPL version:
Terminal window
npm list @yapl-language/yapl.ts
  1. Minimal reproduction case:
import { NodeYAPL } from "@yapl-language/yapl.ts";
const yapl = new NodeYAPL({ baseDir: "./test" });
const result = await yapl.renderString("{{ test }}", { test: "value" });
console.log(result.content);
  1. Error messages and stack traces
  2. Expected vs actual behavior
  3. Environment details (Node.js version, OS, etc.)

This troubleshooting guide should help you resolve most common issues with YAPL. If you encounter problems not covered here, please check the documentation or reach out to the community for help.