cloudflare/cloudflared · error

convert path to UTF-16: %w

Error message

convert path to UTF-16: %w

What it means

After building the security descriptor, createTokenFile converts the token file path to a Windows UTF-16 pointer via windows.UTF16PtrFromString for the Win32 CreateFile call. This conversion fails when the path contains an interior NUL byte (0x00), because Windows paths are NUL-terminated C strings. cloudflared wraps that failure with this message.

Source

Thrown at cmd/cloudflared/windows_service.go:149

	// - (A;;FA;;;SY) -> ACE #2: Ditto but for the Local System user (SY)
	//
	// Relevant Docs:
	//
	// - SecurityDescriptor string as a whole:
	//     https://learn.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format
	// - SID Strings such as BA/SY
	//     https://learn.microsoft.com/en-us/windows/win32/secauthz/sid-strings
	// - ACE Strings such as (A;;FA;;BA)
	//     https://learn.microsoft.com/en-us/windows/win32/secauthz/ace-strings
	const sdString = "O:BAD:P(A;;FA;;;BA)(A;;FA;;;SY)"
	sd, err := windows.SecurityDescriptorFromString(sdString)
	if err != nil {
		return fmt.Errorf("create token security descriptor: %w", err)
	}

	pathRaw, err := windows.UTF16PtrFromString(path)
	if err != nil {
		return fmt.Errorf("convert path to UTF-16: %w", err)
	}

	f, err := windows.CreateFile(
		pathRaw,
		windows.GENERIC_WRITE,
		0,
		&windows.SecurityAttributes{
			Length:             uint32(unsafe.Sizeof(windows.SecurityAttributes{})),
			SecurityDescriptor: sd,
			InheritHandle:      0,
		},
		windows.CREATE_ALWAYS, // Will truncate the file if it exists
		windows.FILE_ATTRIBUTE_NORMAL,
		0,
	)

	if err != nil {
		return fmt.Errorf("create token file: %w", err)

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Remove NUL bytes from the path before use: strings.TrimSuffix(p, "\x00") or strings.ReplaceAll(p, "\x00", "")
  2. Check where the path originates (config file, env var) and fix the producer so it trims at the first NUL
  3. Call strings.Trim(configDir, "\x00 ") after reading environment variables populated by C interop

Example fix

// before
pathRaw, err := windows.UTF16PtrFromString(path)
if err != nil {
	return fmt.Errorf("convert path to UTF-16: %w", err)
}
// after
path = strings.TrimRight(path, "\x00")
if strings.ContainsRune(path, 0) {
	return fmt.Errorf("path contains interior NUL byte: %q", path)
}
pathRaw, err := windows.UTF16PtrFromString(path)
if err != nil {
	return fmt.Errorf("convert path to UTF-16: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

// Go: reject NUL bytes before any Win32 path call
func validWinPath(p string) bool { return p != "" && !strings.ContainsRune(p, 0) && len(p) <= 32767 }

Type guard

func hasInteriorNul(s string) bool { return strings.IndexByte(s, 0) >= 0 }

Try / catch

if err := installWindowsService(ctx); err != nil {
	if strings.Contains(err.Error(), "convert path to UTF-16") {
		log.Error().Msg("path contains NUL bytes; sanitize inputs feeding the path")
	}
	return err
}

Prevention

When it happens

Trigger: The `path` argument passed to createTokenFile contains an embedded NUL character, so UTF16PtrFromString cannot produce a valid *uint16 path.

Common situations: A config/env value feeding the path was read from a buffer that was not trimmed at the NUL terminator; programmatic misuse of cloudflared internals with a Go string built from a C buffer.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/6b6e2ec38367ff38. Report an issue: GitHub.