Mintplex-Labs/anything-llm · warning

Invalid filename format

Error message

Invalid filename format

What it means

Returned (HTTP 400) by GET /agent-skills/generated-files/:filename when createFilesLib.parseFilename(filename) returns null. The filename must match the generated-file naming scheme {fileType}-{36-char uuid}.{extension} (regex /^([a-z]+)-([a-f0-9-]{36})\.(\w+)$/i in create-files/lib.js:194) because the endpoint only serves files created by the agent's file-creation tool. Human-readable names, missing extensions, wrong UUID length, or extra characters all fail here before any database or storage lookup.

Source

Thrown at server/endpoints/agentFileServer.js:43

   * Download a generated file by its storage filename.
   * Validates that the requesting user has access to the workspace
   * where the file was generated.
   */
  app.get(
    "/agent-skills/generated-files/:filename",
    [validatedRequest, flexUserRoleValid([ROLES.all])],
    async (request, response) => {
      try {
        const user = await userFromSession(request, response);
        const { filename } = request.params;
        if (!filename)
          return response.status(400).json({ error: "Filename is required" });

        // Validate filename format
        const parsed = createFilesLib.parseFilename(filename);
        if (!parsed) {
          return response
            .status(400)
            .json({ error: "Invalid filename format" });
        }

        // Find a chat or scheduled job run that references this file
        const fileSource = await findFileSource(filename, {
          user,
          isMultiUser: multiUserMode(response),
        });

        if (!fileSource) {
          return response.status(404).json({
            error: "File not found or access denied",
          });
        }

        // Retrieve the file from storage
        const fileData = await createFilesLib.getGeneratedFile(filename);
        if (!fileData) {

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Use the exact storage filename from the chat's artifact/download URL — never the human-readable display name
  2. If constructing links yourself, build them as `${fileType}-${uuid}.${ext}` matching the 36-char uuid convention
  3. Check for double-encoding when names pass through proxies or query strings

Example fix

// before: display name does not match the storage scheme
const url = `/agent-skills/generated-files/${encodeURIComponent('Q3 Report.pptx')}`; // 400

// after: take the storage filename the backend returned with the artifact
const url = `/agent-skills/generated-files/${encodeURIComponent(artifact.storageFilename)}`; // e.g. pptx-<uuid>.pptx
Defensive patterns

Strategy: type-guard

Validate before calling

const GENERATED_FILE_PATTERN = /^([a-z]+)-([a-f0-9-]{36})\.(\w+)$/i;
if (!GENERATED_FILE_PATTERN.test(filename))
  throw new Error(`not a storage filename: ${filename}`);

Type guard

function isStorageFilename(filename) {
  return typeof filename === 'string' &&
    /^([a-z]+)-([a-f0-9-]{36})\.(\w+)$/i.test(filename);
}

Try / catch

try { const blob = await download(filename); }
catch (e) {
  if (e.status === 400 && /filename format/i.test(e.body?.error ?? ''))
    throw new Error(`use the artifact's storage filename, not its display name`);
}

Prevention

When it happens

Trigger: GET /agent-skills/generated-files/report.pdf (display name instead of storage name like pptx-3f2c...-uuid.pptx); filename with no dot/extension; a uuid segment shorter than 36 chars; path separators or '..' smuggled into the param; double-encoded names that decode after the route match.

Common situations: Users copying the pretty display filename from chat instead of the download link; clients building URLs from the original prompt title; copy/paste truncating the long uuid; URL-encoding differences (%20 vs +) mangling the name.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/959b38d2828036ea. Report an issue: GitHub.