wavetermdev/waveterm · error

doctype not supported

Error message

doctype not supported

What it means

vdom.Bind's HTML tokenizer encountered a <!DOCTYPE ...> declaration, which the minimal bind-HTML grammar does not support. Bind expects a plain fragment of HTML (elements, text, comments, bind tags) — a doctype means a full HTML document was passed where only a fragment is expected, so parsing stops with this error.

Source

Thrown at pkg/vdom/vdom_html.go:385

				appendChildToStack(elemStack, &VDomElem{Tag: WaveTextTag, Props: map[string]any{"text": binding}})
				continue
			}
			elem := tokenToElem(token, params)
			appendChildToStack(elemStack, elem)
		case htmltoken.TextToken:
			if token.Data == "" {
				continue
			}
			textStr := processTextStr(token.Data)
			if textStr == "" {
				continue
			}
			elem := TextElem(textStr)
			appendChildToStack(elemStack, &elem)
		case htmltoken.CommentToken:
			continue
		case htmltoken.DoctypeToken:
			tokenErr = errors.New("doctype not supported")
			break outer
		case htmltoken.ErrorToken:
			if iter.Err() == io.EOF {
				break outer
			}
			tokenErr = iter.Err()
			break outer
		}
	}
	if tokenErr != nil {
		errTextElem := TextElem(tokenErr.Error())
		appendChildToStack(elemStack, &errTextElem)
	}
	rtn := finalizeStack(elemStack)
	fixupStyleAttributes(rtn, params, nil)
	return rtn
}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Strip the <!DOCTYPE ...> declaration (and usually <html>/<head>/<body> wrappers) before passing markup to vdom.Bind.
  2. Configure your template loader to read only the body fragment of HTML documents.
  3. Convert full documents upstream with an HTML parser (e.g. golang.org/x/net/html) and pass Bind only the extracted fragment.

Example fix

// before
content, _ := os.ReadFile("page.html") // includes <!DOCTYPE html>
elem, err := vdom.Bind(string(content), params)
// after
content, _ := os.ReadFile("page.html")
fragment := stripDoctypeAndBodyExtract(string(content)) // remove <!DOCTYPE ...> prolog
elem, err := vdom.Bind(fragment, params)
Defensive patterns

Strategy: validation

Validate before calling

if strings.HasPrefix(strings.TrimSpace(html), "<!DOCTYPE") || strings.HasPrefix(strings.ToLower(strings.TrimSpace(html)), "<!doctype") {
    return fmt.Errorf("pass a document fragment, not a full HTML document, to vdom.Bind")
}

Try / catch

elem, err := vdom.Bind(html, params)
if err != nil && strings.Contains(err.Error(), "doctype not supported") {
    return fmt.Errorf("strip the <!DOCTYPE> prolog before binding: %w", err)
}
if err != nil {
    return err
}

Prevention

When it happens

Trigger: Passing an entire HTML document including its <!DOCTYPE html> prolog to vdom.Bind instead of just the body/fragment content.

Common situations: Loading .html files saved from browsers or exported documents and feeding them whole into Bind; server-rendering pipelines that hand the full document to the VDOM layer; misconfigured template loaders that do not strip the doctype.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/a6f88599aa059e30. Report an issue: GitHub.