{"record":{"id":"ab50cb4ecc602f87","repo":"dotnet/aspnetcore","slug":"fileextensions-validator-requires-a-non-empty-ext","errorCode":null,"errorMessage":"FileExtensions validator requires a non-empty \"extensions\" parameter.","messagePattern":"FileExtensions validator requires a non-empty \"extensions\" parameter\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/Components/Web.JS/src/Validation/Validators/FileExtensions.ts","lineNumber":12,"sourceCode":"// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under the MIT license.\n\nimport { ValidationContext, ValidationResult, Validator, pass, fail } from '../ValidationTypes';\n\n// Validates that the filename ends with an allowed extension (case-insensitive).\n// Extensions param is comma-separated with dot prefix (e.g. \".png,.jpg,.gif\").\n// Throws if the mandatory `extensions` parameter is missing.\nexport const fileExtensionsValidator: Validator = (context: ValidationContext): ValidationResult => {\n  const { value, params } = context;\n  if (!params.extensions) {\n    throw new Error('FileExtensions validator requires a non-empty \"extensions\" parameter.');\n  }\n\n  if (!value) {\n    return pass();\n  }\n\n  // Build regex from comma-separated extensions, stripping dots and escaping regex metacharacters.\n  const extensions = params.extensions.split(',')\n    .map(ext => ext.trim().replace(/^\\./, ''))\n    .filter(ext => ext.length > 0)\n    .map(ext => ext.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'))\n    .join('|');\n\n  if (!extensions) {\n    return pass();\n  }\n\n  return new RegExp(`\\\\.(${extensions})$`, 'i').test(value) ? pass() : fail();","sourceCodeStart":1,"sourceCodeEnd":30,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/Components/Web.JS/src/Validation/Validators/FileExtensions.ts#L1-L30","documentation":"Thrown by the FileExtensions validator (FileExtensions.ts:12) when params.extensions is falsy. This validator checks that an uploaded filename ends with one of the allowed extensions (e.g., '.png,.jpg'); without the extensions list there is nothing to validate, so it throws to surface the misconfiguration.","triggerScenarios":"Invoking the fileExtensions validator with a params object missing 'extensions' or with extensions='' / null. Normally emitted from [FileExtensions(Extensions=\".png,.jpg\")]; if the attribute's data-val-fileextensions-extensions metadata is absent the JS validator cannot run.","commonSituations":"Model has [FileExtensions] but the attribute argument is empty or the tag helper does not emit data-val-fileextensions-extensions. Custom input rendering that drops data-* attributes. Manually registering the validator without supplying extensions.","solutions":["Add [FileExtensions(Extensions = \".png,.jpg,.gif\")] to the IFormFile/string property and confirm the input renders data-val-fileextensions-extensions=\".png,.jpg,.gif\".","When wiring manually, pass params: { extensions: '.png,.jpg' } (comma-separated, leading dots optional).","Confirm no custom HTML helper is stripping data-val-* attributes from file inputs.","Verify the attribute is on the property bound to the uploaded file, not a related display field."],"exampleFix":"// before\n<input type=\"file\" name=\"Upload\" data-val-fileextensions />\n\n// after\n<input type=\"file\" name=\"Upload\" data-val-fileextensions data-val-fileextensions-extensions=\".png,.jpg\" />","handlingStrategy":"validation","validationCode":"function hasExtensionsParam(params: Record<string, unknown>): boolean {\n  return Boolean(params && typeof params.extensions === 'string' && params.extensions.length > 0);\n}","typeGuard":"function isFileExtensionsConfigured(p: any): p is { extensions: string } {\n  return p && typeof p.extensions === 'string' && p.extensions.trim().length > 0;\n}","tryCatchPattern":null,"preventionTips":["Always supply Extensions=\".png,.jpg\" on [FileExtensions].","Confirm data-val-fileextensions-extensions renders on the input.","When wiring manually pass { extensions: '.png,.jpg' }.","Guard against tag helpers stripping data-* attributes."],"tags":["validation","blazor","forms","file-upload","configuration"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}