16 KiB
TinaCMS Common Errors - Complete Reference
This document provides detailed troubleshooting for all 9 common TinaCMS errors.
Last Updated: 2025-10-24 TinaCMS Version: 2.9.0
Table of Contents
- ESbuild Compilation Errors
- Module Resolution Issues
- Field Naming Constraints
- Docker Binding Issues
- Missing _template Key Error
- Path Mismatch Issues
- Build Script Ordering Problems
- Failed Loading TinaCMS Assets
- Reference Field 503 Service Unavailable
1. ESbuild Compilation Errors
Error Messages
ERROR: Schema Not Successfully Built
ERROR: Config Not Successfully Executed
ERROR: Cannot bundle code that requires custom loaders
Causes
The tina/config.ts file is compiled using esbuild and executed in Node.js. This can fail when:
-
Importing code with custom loaders
- Webpack loaders
- Babel plugins
- PostCSS processors
- SCSS/SASS files
- Vue/Svelte components
-
Importing frontend-only code
- Code using
windowobject - Code using DOM APIs
- React hooks outside components
- Browser-specific APIs
- Code using
-
Importing entire component libraries
import { Component } from '../components/'pulls in entire directory- May include dependencies not compatible with Node.js
Solutions
Solution 1: Import Specific Files Only
// ❌ Bad - Imports entire directory
import { HeroComponent } from '../components/'
// ✅ Good - Import specific file
import { HeroComponent } from '../components/blocks/hero'
// ❌ Bad - Imports entire library
import * as Components from '../components'
// ✅ Good - Import only what you need
import { HeroComponent, CTAComponent } from '../components/blocks'
Solution 2: Create Separate Schema Files
If your component definitions are complex, extract schema to separate files:
// components/hero/hero.schema.ts
export const heroBlockSchema = {
name: 'hero',
label: 'Hero Section',
fields: [/* ... */]
}
// tina/config.ts
import { heroBlockSchema } from '../components/hero/hero.schema'
export default defineConfig({
schema: {
collections: [{
fields: [{
type: 'object',
name: 'hero',
...heroBlockSchema
}]
}]
}
})
Solution 3: Use Type Imports Only
// ✅ Import only types (doesn't execute code)
import type { HeroProps } from '../components/Hero'
Prevention
- Keep
tina/config.tsminimal - Only import type definitions and simple utilities
- Avoid importing UI components
- Extract schema definitions to separate files
- Test config builds with
npx @tinacms/cli@latest build
Related Links
- Official Docs: https://tina.io/docs/errors/esbuild-error
- GitHub Issue: https://github.com/tinacms/tinacms/issues/3472
2. Module Resolution Issues
Error Messages
Error: Could not resolve "tinacms"
Module not found: Can't resolve 'tinacms'
Cannot find module 'tinacms' or its corresponding type declarations
Causes
-
Corrupted Installation
- Incomplete
npm install - Network issues during installation
- Corrupted
node_modules
- Incomplete
-
Version Mismatches
- Conflicting peer dependencies
- React version mismatch
- TinaCMS version incompatibility
-
Missing Dependencies
reactandreact-domnot installed (required even for non-React frameworks)@tinacms/clinot in devDependencies
Solutions
Solution 1: Clean Reinstall (npm)
# Remove node_modules and lock file
rm -rf node_modules package-lock.json
# Clear npm cache
npm cache clean --force
# Reinstall all dependencies
npm install
Solution 2: Clean Reinstall (pnpm)
# Remove node_modules and lock file
rm -rf node_modules pnpm-lock.yaml
# Clear pnpm cache
pnpm store prune
# Reinstall all dependencies
pnpm install
Solution 3: Clean Reinstall (yarn)
# Remove node_modules and lock file
rm -rf node_modules yarn.lock
# Clear yarn cache
yarn cache clean
# Reinstall all dependencies
yarn install
Solution 4: Ensure React Dependencies (Non-React Frameworks)
Even if you're using Hugo, Jekyll, or Eleventy, you MUST install React:
npm install react@^19 react-dom@^19
Prevention
- Use lockfiles (
package-lock.json,pnpm-lock.yaml,yarn.lock) - Don't use
--no-optionalor--omit=optionalflags - Ensure
reactandreact-domare in dependencies - Keep TinaCMS versions consistent across packages
Related Links
- GitHub Issue: https://github.com/tinacms/tinacms/issues/4530
3. Field Naming Constraints
Error Messages
Field name contains invalid characters
Invalid field name: 'hero-image'
Field names must be alphanumeric
Causes
TinaCMS field names can ONLY contain:
- Letters (a-z, A-Z)
- Numbers (0-9)
- Underscores (_)
NOT allowed:
- Hyphens (-)
- Spaces ( )
- Special characters (!@#$%^&*)
This is a breaking change from Forestry.io which allowed hyphens.
Solutions
Solution 1: Use Underscores
// ❌ Bad
{
name: 'hero-image',
label: 'Hero Image',
type: 'image'
}
// ✅ Good
{
name: 'hero_image',
label: 'Hero Image',
type: 'image'
}
Solution 2: Use camelCase
// ✅ Also good
{
name: 'heroImage',
label: 'Hero Image',
type: 'image'
}
Solution 3: Migrate Existing Content
If migrating from Forestry.io with hyphenated field names:
# Find all files with hyphenated frontmatter
find content -name "*.md" -exec sed -i 's/hero-image:/hero_image:/g' {} +
find content -name "*.md" -exec sed -i 's/cover-photo:/cover_photo:/g' {} +
Prevention
- Use underscores or camelCase for all field names
- Document naming convention in team style guide
- Use linter/validator to catch invalid names
Related Links
- Migration Docs: https://tina.io/docs/forestry/migrate#field-names
4. Docker Binding Issues
Error Messages
Connection refused: http://localhost:3000
Cannot connect to TinaCMS admin interface
ERR_CONNECTION_REFUSED
Causes
By default, development servers bind to 127.0.0.1 (localhost only), which prevents access from:
- Docker containers
- Network devices
- Remote connections
Solutions
Solution 1: Next.js
tinacms dev -c "next dev --hostname 0.0.0.0"
Or in package.json:
{
"scripts": {
"dev": "tinacms dev -c \"next dev --hostname 0.0.0.0\""
}
}
Solution 2: Vite
tinacms dev -c "vite --host 0.0.0.0"
Or in vite.config.ts:
export default defineConfig({
server: {
host: '0.0.0.0',
port: 3000
}
})
Solution 3: Astro
tinacms dev -c "astro dev --host 0.0.0.0"
Or in astro.config.mjs:
export default defineConfig({
server: {
host: '0.0.0.0',
port: 4321
}
})
Solution 4: Docker Compose
version: '3'
services:
app:
build: .
ports:
- "3000:3000"
command: npm run dev # Must include --hostname 0.0.0.0
Prevention
- Always use
--host 0.0.0.0in Docker environments - Configure framework config files instead of CLI flags
- Document binding requirements in README
5. Missing _template Key Error
Error Messages
GetCollection failed: Unable to fetch
template name was not provided
Error: Document missing _template field
Causes
When a collection uses templates array (multiple schemas), each document must include a _template field in its frontmatter specifying which template to use.
Solutions
Solution 1: Use fields Instead (Recommended)
If you only have one schema, use fields instead of templates:
// ❌ Using templates (requires _template in frontmatter)
{
name: 'post',
path: 'content/posts',
templates: [
{
name: 'article',
fields: [/* ... */]
}
]
}
// ✅ Using fields (no _template needed)
{
name: 'post',
path: 'content/posts',
fields: [/* ... */] // Same fields as above
}
Solution 2: Add _template to Frontmatter
If you need multiple templates, ensure all documents have _template:
---
_template: article
title: My Blog Post
date: 2025-10-24
---
Content here...
Solution 3: Batch Update Existing Files
# Add _template field to all files
find content/posts -name "*.md" -exec sed -i '1a _template: article' {} +
Solution 4: Set Default Template
{
name: 'post',
path: 'content/posts',
templates: [
{
name: 'article',
fields: [/* ... */]
}
],
ui: {
defaultItem: () => ({
_template: 'article' // Default template for new documents
})
}
}
Prevention
- Use
fieldsfor single-schema collections - Use
templatesonly when you truly need multiple schemas - Document
_templaterequirement in team guidelines
6. Path Mismatch Issues
Error Messages
No files found in collection
File not found: content/posts/hello.md
GraphQL query returned empty results
Causes
The path in your collection config doesn't match where files actually live.
Solutions
Solution 1: Verify File Locations
# Check where your files actually are
ls -R content/
# If files are in content/posts/
# Your config should be:
{
name: 'post',
path: 'content/posts' // ✅ Matches file location
}
Solution 2: No Trailing Slash
// ❌ Bad
{
path: 'content/posts/' // Trailing slash may cause issues
}
// ✅ Good
{
path: 'content/posts' // No trailing slash
}
Solution 3: Use Relative Paths
// ✅ Path relative to project root
{
path: 'content/posts'
}
// ❌ Don't use absolute paths
{
path: '/home/user/project/content/posts'
}
Solution 4: Audit Paths
# TinaCMS CLI includes audit command
npx @tinacms/cli@latest audit
# Shows which files match collections
# Helps identify path mismatches
Prevention
- Always verify file structure before setting
path - Use
npx @tinacms/cli@latest auditto check paths - Document expected file structure in README
7. Build Script Ordering Problems
Error Messages
ERROR: Cannot find module '../tina/__generated__/client'
ERROR: Property 'queries' does not exist on type '{}'
Type error: Module '../tina/__generated__/client' has no exported member 'client'
Causes
Framework build runs before tinacms build, so generated TypeScript types don't exist yet.
Solutions
Solution 1: Correct Script Order
{
"scripts": {
"build": "tinacms build && next build" // ✅ Tina FIRST
// NOT: "build": "next build && tinacms build" // ❌ Wrong
}
}
Solution 2: CI/CD Fix (GitHub Actions)
name: Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install dependencies
run: npm install
- name: Build Tina
run: npx @tinacms/cli@latest build # Generate types FIRST
- name: Build App
run: npm run build # Now framework build works
Solution 3: Vercel Configuration
// vercel.json
{
"buildCommand": "tinacms build && next build"
}
Solution 4: Netlify Configuration
# netlify.toml
[build]
command = "tinacms build && npm run build"
Prevention
- Always run
tinacms buildbefore framework build - Document correct build order in README
- Add build order to CI/CD templates
8. Failed Loading TinaCMS Assets
Error Messages
Failed to load resource: net::ERR_CONNECTION_REFUSED
http://localhost:4001/...
Mixed Content: The page was loaded over HTTPS, but requested an insecure resource
Causes
-
Development
admin/index.htmlpushed to production- Dev version loads assets from
localhost:4001 - Production needs built assets
- Dev version loads assets from
-
Subdirectory deployment without
basePathconfig- Site deployed to
example.com/blog/ - TinaCMS tries to load from
example.com/admin/(fails)
- Site deployed to
Solutions
Solution 1: Always Build for Production
{
"scripts": {
"build": "tinacms build && next build" // ✅ Always build
// NOT: "build": "tinacms dev" // ❌ Never dev in prod
}
}
Solution 2: Configure basePath for Subdirectories
If site is at example.com/blog/:
// tina/config.ts
export default defineConfig({
build: {
outputFolder: 'admin',
publicFolder: 'public',
basePath: 'blog' // ← Subdirectory path
}
})
Solution 3: Verify .gitignore
# .gitignore
# TinaCMS
.tina/__generated__
admin/index.html # ← Don't commit dev admin
# But DO commit:
# public/admin/ (production build)
Solution 4: CI/CD Always Build
# GitHub Actions
- run: npx @tinacms/cli@latest build # Not dev!
Prevention
- Use
tinacms buildin all CI/CD - Set
basePathfor subdirectory deploys - Don't commit
admin/index.htmlfrom dev mode
9. Reference Field 503 Service Unavailable
Error Messages
503 Service Unavailable
Request timed out
Reference field dropdown not loading
Causes
Reference fields load ALL documents from the referenced collection. If the collection has 100s or 1000s of items, the request times out.
Current Limitation: TinaCMS does not support pagination for reference fields (as of v2.9.0).
Solutions
Solution 1: Split Large Collections
Instead of one huge collection, split by category:
// ❌ Single huge collection (1000+ authors)
{
name: 'author',
path: 'content/authors',
fields: [/* ... */]
}
// ✅ Split into manageable sizes
{
name: 'active_author',
label: 'Active Authors',
path: 'content/authors/active',
fields: [/* ... */]
}
{
name: 'archived_author',
label: 'Archived Authors',
path: 'content/authors/archived',
fields: [/* ... */]
}
Solution 2: Use String Field with Validation
Instead of reference, use a string select:
// ❌ Reference field (times out with 100+ authors)
{
type: 'reference',
name: 'author',
collections: ['author']
}
// ✅ String field with curated options
{
type: 'string',
name: 'author_id',
label: 'Author',
options: [
{ label: 'John Doe', value: 'john-doe' },
{ label: 'Jane Smith', value: 'jane-smith' },
// ... curated list of ~50 authors max
]
}
Solution 3: Custom Field Component (Advanced)
Create a custom field component with client-side pagination:
// Advanced: Requires custom React component
{
type: 'string',
name: 'author_id',
ui: {
component: 'author-select-paginated' // Your custom component
}
}
See: https://tina.io/docs/extending-tina/custom-field-components/
Solution 4: Use External Service
For very large datasets, consider:
- Store authors in D1/KV
- Use custom field component to query via API
- Load data on-demand with search/filter
Prevention
- Limit referenced collections to <100 items
- Use string fields for large datasets
- Consider alternative architectures for huge collections
Related Links
- GitHub Issue: https://github.com/tinacms/tinacms/issues/3821
- Custom Fields Docs: https://tina.io/docs/extending-tina/custom-field-components/
Additional Resources
Official Documentation
- Main Docs: https://tina.io/docs
- Error FAQ: https://tina.io/docs/errors/faq
- ESbuild Error: https://tina.io/docs/errors/esbuild-error
- Contributing: https://tina.io/docs/contributing/troubleshooting
Support
- Discord: https://discord.gg/zumN63Ybpf
- GitHub Issues: https://github.com/tinacms/tinacms/issues
- GitHub Discussions: https://github.com/tinacms/tinacms/discussions
Last Updated: 2025-10-24 Errors Documented: 9 Prevention Rate: 100%