Classic ASP Upload Errors and How to Fix Them
The error messages you will actually hit, in plain language, with the setting that fixes each one.
Classic ASP upload failures are famously unhelpful: a blank page, a bare 500, or a form that silently does nothing. Almost all of them are one of the following. Work down the list — they are ordered by how often they turn out to be the cause.
Request.Form is empty, and no error appears
Cause: the form has enctype="multipart/form-data", and Classic ASP does
not parse that encoding. Every field, not just the file, disappears from Request.Form.
Fix: read the fields out of the raw body with a parser or upload script. With ASP Uploader the file travels separately, so your other form fields keep working normally:
<%
Response.Write Request.Form("customer_name") ' still works
Response.Write Request.Form("myuploader") ' "/"-separated file GUIDs
%>
Request object error 'ASP 0104 : 80004005' — Operation not Allowed
Cause: the posted body is larger than maxRequestEntityAllowed, whose
default is 200,000 bytes. It is not about the file being "too big" in any general sense — 200 KB
is simply the ceiling.
<!-- web.config -->
<system.webServer>
<asp maxRequestEntityAllowed="1073741824" />
</system.webServer>
ASP 0104 also appears when Request.BinaryRead is called after
Request.Form has already been touched. Read the binary body first, or not at all.
HTTP 404.13 — Content length too large
Cause: a different limit. Request filtering caps the body at ~28.6 MB by default, independently of the ASP limit.
<system.webServer>
<security><requestFiltering>
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering></security>
</system.webServer>
These two limits are separate and both apply. Raising one and still failing is the single most common "I already fixed that" moment in ASP upload debugging.
Microsoft VBScript runtime error '800a0046' — Permission denied
Cause: the application pool identity cannot write to the destination folder.
Fix: find the identity (IIS Manager → Application Pools → Advanced Settings
→ Identity; usually ApplicationPoolIdentity, which means
IIS AppPool\<PoolName>), then grant Modify:
icacls "C:\inetpub\wwwroot\mysite\uploads" /grant "IIS AppPool\DefaultAppPool":(OI)(CI)M
Check the temp folder too. An uploader that streams to temp before moving needs write access in both places, and the error will point at whichever it hits first.
Path not found / Invalid procedure call from MoveTo
Cause: the destination directory does not exist. MoveTo will not create it.
<%
Dim fso, destDir
Set fso = Server.CreateObject("Scripting.FileSystemObject")
destDir = Server.MapPath("uploads")
If Not fso.FolderExists(destDir) Then fso.CreateFolder destDir
mvcfile.MoveTo destDir & "\" & storedName
%>
It also fires when the file name contains characters illegal on NTFS — : * ? " < > |
— which is another reason to generate your own storage names.
The request timed out / blank page after a long wait
Cause: Server.ScriptTimeout (90 s default) or the IIS connection timeout
(120 s default) expired mid-upload.
<% Server.ScriptTimeout = 3600 %>
Also check the app pool's Idle Time-out (default 20 minutes) — on a site where users do nothing but upload, IIS can decide the pool is idle and recycle it mid-transfer. Set it to 0.
If the failure happens at a consistent elapsed time regardless of file size, it is a timeout. If it happens at a consistent file size, it is a limit.
Out of memory, or the app pool recycles mid-upload
Cause: Request.BinaryRead buffers the whole post, and parsing it
allocates again. Peak usage is two to three times the file size, per concurrent upload.
Fix: stop buffering whole files. A chunked uploader keeps peak memory at one chunk regardless of file size — see uploading large files.
Plain HTTP 500 with no detail
IIS hides the real error from remote browsers by default. Turn detail on temporarily:
<system.webServer>
<httpErrors errorMode="Detailed" />
<asp scriptErrorSentToBrowser="true" />
</system.webServer>
<system.web>
<customErrors mode="Off" />
</system.web>
Turn this back off before going live. Detailed ASP errors leak physical paths, connection strings and source lines to anyone who can trigger them.
Also check the Windows Event Log and the IIS logs in
C:\inetpub\logs\LogFiles — the sub-status code (500.19, 500.100, 404.13) is the
part that actually identifies the problem.
License Error : (4) license expired!
Cause: specific to ASP Uploader — the trial licence file has passed its date.
Fix: replace aspuploader/license/aspuploader.lic with a current file.
Download a fresh trial package, or drop in the licence issued with your purchase. Nothing else needs
to change; the file is read at runtime.
413 Request Entity Too Large
Cause: something in front of IIS rejected the request — Cloudflare (100 MB on
Free/Pro), nginx (client_max_body_size, 1 MB default), an ARR proxy, or a corporate
firewall. IIS never saw it, so IIS settings will not help.
Fix: raise the limit on that device, or chunk the upload so each request stays small.
A five-minute diagnostic
- Upload a 10 KB file. Fails? The problem is code or permissions, not size.
- Upload 500 KB. Fails where 10 KB worked?
maxRequestEntityAllowed. - Upload 50 MB. Fails where 500 KB worked?
maxAllowedContentLengthor a proxy. - Fails at a consistent time rather than a consistent size? Timeout.
- Works alone, fails under load? Memory — you are buffering whole files.
- Check
C:\inetpub\logs\LogFilesfor the sub-status code before changing anything else.
Frequently asked questions
What does ASP 0104 Operation not Allowed mean?
The posted body exceeded maxRequestEntityAllowed (200 KB by default), or
Request.BinaryRead was called after Request.Form had been read.
Why does my upload work locally but fail on the live server?
Usually folder permissions for the application pool identity, or a proxy/CDN body limit that does not exist on your development machine.
Where are the IIS logs for a failed upload?
C:\inetpub\logs\LogFiles\W3SVC<siteid>. The sub-status column is what identifies
the failure.
Skip the plumbing
ASP Uploader does everything on this page out of the box: multi-file selection, a real progress bar, client and server validation, chunked large-file transfer, and no COM component to register. Drop the folder on your server and add one include line.