windmill-labs/windmill · error

Content of raw app file ${filePath} is not a string

Error message

Content of raw app file ${filePath} is not a string

What it means

When reading a raw app's files from a zip archive during sync, each entry lazily returns its text via getContentText(). The CLI throws this error if the stored content value for a file is not a string, meaning the raw app's `value.files` (or equivalent zip data) holds a non-string (object, number, null) where file text was expected.

Source

Thrown at cli/src/commands/sync/sync.ts:1470

                  filePath === "/DATATABLES.md"
                ) {
                  continue;
                }
                // Strip only a leading `/` (keys are app-root-relative), so the
                // relative path handed to the guard matches what the backend's
                // `strip_prefix('/')` validates — the two must not disagree on a
                // non-`/` key, or a deploy the backend allows would abort the pull.
                const filePathInApp = rawAppPathWithinFolder(
                  finalPath,
                  filePath.replace(/^\//, ""),
                );
                yield {
                  isDirectory: false,
                  path: filePathInApp,
                  async *getChildren() {},
                  async getContentText() {
                    if (typeof content !== "string") {
                      throw new Error(
                        `Content of raw app file ${filePath} is not a string`,
                      );
                    }
                    return content as string;
                  },
                };
              }
            } catch (error) {
              log.error(`Failed to extract files for raw app at path: ${p}`);
              throw error;
            }

            // Yield inline script content and lock files
            for (const s of inlineScripts) {
              yield {
                isDirectory: false,
                path: path.join(finalPath, APP_BACKEND_FOLDER, s.path),
                async *getChildren() {},

View on GitHub (pinned to e474e8803c)

Solutions

  1. Open the raw app definition and make every `value.files` entry a plain string of file text (encode binaries as needed, e.g. base64 with the convention your app uses)
  2. Check CLI/instance version compatibility and upgrade the CLI to match the export format
  3. Re-export the raw app from the instance rather than hand-editing the JSON
  4. If calling this API from code, validate `typeof content === 'string'` before constructing the entry

Example fix

// before
"files": { "index.js": { "content": "console.log(1)" } }
// after
"files": { "index.js": "console.log(1)" }
Defensive patterns

Strategy: type-guard

Validate before calling

const files = rawApp.value.files ?? {};
const bad = Object.entries(files).filter(([, v]) => typeof v !== 'string');
if (bad.length) throw new Error(`non-string file content: ${bad.map(([k]) => k).join(', ')}`);

Type guard

function isStringFileMap(v: unknown): v is Record<string, string> {
  return typeof v === 'object' && v !== null &&
    Object.values(v).every(x => typeof x === 'string');
}

Try / catch

try {
  const text = await entry.getContentText();
} catch (e) {
  if (String(e).includes('is not a string')) {
    // inspect the app definition's value.files entry for this path
  } else throw e;
}

Prevention

When it happens

Trigger: Pushing/pulling a raw app whose `value.files` map contains a non-string value for some file key — e.g. someone pasted an object instead of file text, a tool serialized content as {content: ...}, or an older/newer export format is being read by an incompatible CLI version.

Common situations: Hand-editing or script-generating a raw app JSON with wrong shapes; version mismatch between the instance that exported the app and the CLI reading it; a migration converting binary/encoded file content into objects.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/a0a0dcb84e473141. Report an issue: GitHub.