octobercms/october · error · SystemException

cms::lang.template.invalid_type

Error message

cms::lang.template.invalid_type

What it means

resolveTypeClassName() maps the request's document type to a Halcyon template class and accepts only the six known types: page, partial, layout, content, asset and lang (EditorExtension constants). Any other string throws 'Unknown template type.'

Source

Thrown at modules/cms/classes/editorextension/HasExtensionCrud.php:272

    /**
     * resolveTypeClassName resolves a template type to its class name
     * @param string $documentType
     * @return string
     */
    private function resolveTypeClassName($documentType)
    {
        $types = [
            EditorExtension::DOCUMENT_TYPE_PAGE => Page::class,
            EditorExtension::DOCUMENT_TYPE_PARTIAL => Partial::class,
            EditorExtension::DOCUMENT_TYPE_LAYOUT => Layout::class,
            EditorExtension::DOCUMENT_TYPE_CONTENT => Content::class,
            EditorExtension::DOCUMENT_TYPE_ASSET => Asset::class,
            EditorExtension::DOCUMENT_TYPE_LANG => CmsLang::class
        ];

        if (!array_key_exists($documentType, $types)) {
            throw new SystemException(trans('cms::lang.template.invalid_type'));
        }

        return $types[$documentType];
    }

    /**
     * makeMetadataForNewTemplate builds meta data for new templates
     */
    protected function makeMetadataForNewTemplate(string $documentType): array
    {
        return [
            'mtime' => null,
            'path' => null,
            'theme' => ($theme = $this->getTheme()) ? $theme->getDirName() : null,
            'type' => $documentType,
            'isNewDocument' => true
        ];
    }

View on GitHub (pinned to b608633a7e)

Solutions

  1. Use one of the exact supported type strings: 'page', 'partial', 'layout', 'content', 'asset', 'lang'
  2. Check for typos and casing in the type field
  3. Align the editor JS bundle and PHP backend to the same Winter version so type vocabularies match

Example fix

// before
['type' => 'pages', 'key' => 'index.htm']

// after
['type' => 'page', 'key' => 'index.htm']
Defensive patterns

Strategy: type-guard

Validate before calling

$allowed = ['page', 'partial', 'layout', 'content', 'asset', 'lang'];
if (!in_array($type, $allowed, true)) {
    // reject unknown types before any editor-extension call
    throw new InvalidArgumentException('Unsupported document type: '.$type);
}

Type guard

const DOCUMENT_TYPES = new Set(['page', 'partial', 'layout', 'content', 'asset', 'lang']);
function isDocumentType(t) {
  return typeof t === 'string' && DOCUMENT_TYPES.has(t);
}

Prevention

When it happens

Trigger: An editor-extension request whose documentData/extraData 'type' is not one of the EditorExtension::DOCUMENT_TYPE_* values — custom types, misspellings ('Page', 'pages'), or a type vocabulary from a different Winter version.

Common situations: Custom integrations inventing type names; hand-built JS payloads; older editor bundles running against a newer backend (or vice versa) where the set of types differs (e.g. 'lang' does not exist on older versions).

Related errors


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/075eb1f7c0f484a6. Report an issue: GitHub.