Skip to main content
Ben Nadel at BFusion / BFLEX 2010 (Bloomington, Indiana) with: Daria Norris and Steve Withington
Ben Nadel at BFusion / BFLEX 2010 (Bloomington, Indiana) with: Daria Norris Steve Withington

Negotiation: Discovered File(s) Matching Request: None Could Be Negotiated

By
Published in , Comments (61)

Yesterday, I lost at least two hours trying to figure out why my local copy of a website was throwing 404 (File Not Found) errors. We had just implemented some URL rewriting on the production site and things appeared to be working fine. On my local computer, however, the URL rewriting would only work for some URLs. After a lot of Googling, a little bit of a meltdown, and walk around the block to clear my head, I finally figured out what was going wrong: MultiViews.

For this particular website, we were using Apache to create a more resource-oriented URL scheme. So, where we used to have URLs that looked like this:

/users.cfm?action=view&id=15

... we were going to be moving to a URL scheme that looked more like this:

/users/15/view/

For the majority of URLs in the application, this was working fine. But for a few URLs, this came back as a 404 File Not Found error. When I looked in the Apache error logs, I kept seeing log items like this:

[Thu Jun 23 16:55:06 2011] [error] [client 127.0.0.1] Negotiation: discovered file(s) matching request: /Sites/something.com/users (None could be negotiated).

My experience with the Apache HTTP server is somewhat limited; as such, this error didn't really mean anything coherent to me at the time. And, much of my Googling wasn't really yielding anything too valuable. Finally, however, I did come across a threaded discussion that mentioned "MultiViews". On the Apache website, the effect of Multiviews, as listed under Content Negotiation, is as follows:

If the server receives a request for /some/dir/foo, if /some/dir has MultiViews enabled, and /some/dir/foo does not exist, then the server reads the directory looking for files named foo.*, and effectively fakes up a type map which names all those files, assigning them the same media types and content-encodings it would have if the client had asked for one of them by name. It then chooses the best match to the client's requirements.

This is exactly what was happening! When the user requested the non-existent URL:

/users/15/view/

... Apache was finding this physical file on a per-directory basis:

/users.cfm

... and then using Content Negotiation to try and figure out which file it should served up based on the request headers. And, since I didn't have any file types configured for content negotiation, Apache didn't know how to respond and just returned a 404.

When I checked in my Virtual Host configuration, sure enough, MultiViews was enabled:

Options Indexes FollowSymLinks MultiViews

The moment I removed the MultiViews option:

Options Indexes FollowSymLinks

... everything started working fine.

This goes to show you how bad it is to simply enable settings when you are not sure what they do. I've grown to love my Apache server; but, clearly, there is so much more that I need to learn about it. When it works, it works; but, when it doesn't, I have no idea what's going on.

Want to use code from this post? Check out the license.

Reader Comments

9 Comments

One way to avoid these Apache default directives from affecting you is to always set your DocumentRoot to an empty non-public directory.

Then you can define virtual host files with concise rules, typically in the other or extra directories. The very last lines of tour httpd.conf file point to one of these folders and loads all .conf files located there.

A vhost file typically only requires two sections: VirtualHost, where the site's domain, logs, etc. are setup and a Directory section with all your rules.

15,880 Comments

@Claude,

I think this (what you are saying) is what my Apache config actually had in it right out of the box. It set some root directory and turned off all options. It was totally *me* who added MultiViews in the Virtual Host option set. I think I just turned on everything that was there since I had no idea what any of it did :)

9 Comments

Yes, I looked at the original* http.conf files on my iMac and Linux server and Mac and those directives are there by default for the DocumentRoot. Maybe you copied those settings elsewhere without reading up on them. :)

*Call me crazy, but I do keep a copy of the original for most server configs.

15,880 Comments

@Claude,

Yeah, I probably did :) I come from an IIS background (not that I ever knew IIS all that well) and I think I was just thrilled that I could get Apache to work at all!

15,880 Comments

@Brad,

I tried to remove the FollowSymLinks and it seemed to break the URL Rewriting. I just did a bit of Googleing and found:

"Options +FollowSymLinks is an Apache directive, prerequisite for mod_rewrite"

So, it must be doing something important.

2 Comments

Interesting, I do not use that at all, unless I need to link directors (symlink) as I have no need. My computer, dev and production environments all run on Ubuntu though. Windows is increasingly becoming enigmatic to me.

SymLinks is something windows doesn't really have, afaik so I was curious as to why it might be needed.

For sake of argument this is what my personal environment looks like for a random site. As I do not care about local security really, it makes things quick.

<Directory /home/brad/workd/hv/hv >
Allow from all
</Directory>

I then have my rewrite in .htacess which also doesn't use follow symlinks.

for simplicity it's simply

RewriteEngine on
RewriteRule ^(.*)$ index.php/$1 [L]

Super curious. Maybe that's what the docs mean by having it

The rewrite engine may be used in .htaccess files and in <Directory> sections, with some additional complexity.

So, since I am using .htaccess I don't need it. You may be using directory so you do ?

290 Comments

@David, we Mac folks tend to separate target and action. It's built right into Xcode 4, in fact. To establish a target/action connection, you use drag-and-drop in the Interface Builder window. Drag from a control to the setter method of a value you want it to control, for example.

In many ways, it's like the CSS cascade. That's a REALLY arcane analogy, so let me explain:

Suppose you've defined class="major" hotlinks to be in a larger font than those that don't have that class. You can also define that all hotlinks to :hover in some cool way unrelated to font size. The class="major" hotlinks will highlight that way too, because you've separated target and action.

By defining ?action=view&id=28, Ben has allowed his code to do cfif IsDefined("URL.id") and establish identity in a way that can be shared across numerous actions. So the complexity is encoded into the data structure (ampersand-delimited list of equals-delimited lists), allowing the underlying code to be simpler.

6 Comments

Not really sure I see the comparison between this situation and multi-inheritence in css.

In my mind this situation is closer to calling a method on a static object and passing it the ID of the instance to perform the relevant action on:
widget.cfm?Update=123&...
seems very similar, from a programming syntax point of view, to:
widget.Update(123,...)
and the are often times an action may not need an ID, like creating a new object.

Just seems that using 2 variables is not necessary in this circumstance.

290 Comments

@David, well, I said it was an arcane analogy.

The idea is that, by not hardwiring targets to actions up front, you allow reuse of parts and reduce combinatorial explosion. In the CSS example, combinatorial explosion would have been defining a.major, a.major:hover, a.minor, a.minor:hover, etc, with plenty of redundancy across the selectors. But defining only a.major and a:hover, you reuse the :hover properties without redundancy. No class="minor" needed. By doing less, more gets done. Probably faster too.

Perhaps a better analogy would be normalization of a relational database. Separating target and action is logical atomism. Making "view" imply both action and id, you are denormalizing the interface. As all theorists acknowledge, sometimes it's just practical to denormalize, but the converse is also true. Sometimes it's just practical to normalize.

6 Comments

Again not really seeing how this relates to normalization, the core aspect of normalization is elimination of redundant and/or duplicate data. Another very small benefit of my style is it can allow calling 2 methods in 1 http call, ie: widget.cfm?Delete=#ThisID#&View=#NextID# , I don't use it that way very often, but it can be handy in some circumstances.

15,880 Comments

@Brad,

To be honest, some of what you are saying goes over my head. I am not that great at Apache (I'm running on Mac locally, FYI). It might have to do with the way I have the core httpd config set up?

@David,

I think what Steve is saying is that you can break apart different aspects of the routing. So, for example, if I use Action and ID, I can apply uniform security (for example) before I even get to the part of the page where the "ID" comes into effect.

For example, I might have something like this in my request handling (pseudo code):

<cfif not userCanPerformAction( user, url.action )>
	<cfthrow type="AccessDenied" />
</cfif>

By using a uniform action variable, I can use a bit of a simpler divide-and-conquer approach to routing rather than having to figure out special variables for each.

Of course, this all depends on the underlying framework you have to be using. I use a front-controller style workflow where most things go through index.cfm. But, if you use a page-controller style workflow where things typically all different top-level pages, I see no reason again your approach.

1 Comments

Thank you for this post!

I don't use WebDav generally, but was setting it up on my Ubuntu box at home to allow me to synchronize my KeePass database more easily. When I'd try to save any changes to the webdav area I was getting "404 file not found" and it left me with a KeePass.kdbx.tmp file. Removing "MultiViews" fixed it.

I would never, ever have found this on my own.

I'm leaving this (admittedly mostly extraneous) here in case other KeePass users come googling.

15,880 Comments

@Tim,

My pleasure! I posted this up so hopefully people wouldn't have to bang their heads against the wall. I make no joke when I say that I lost over 2 hours of time just trying to figure this baby beast out!

1 Comments

A little Addendum:

For those people, who have no access to the Apache Configuration (as is the case with my Provider, i cant turn off MultiViews):

Simply avoid filenames that match the virtual directory names.

In my Case:
www.mycustomersdomain.at/kunden
was rewritten to
www.mycustomersdomain.at/kunden.php?page=kunden
and resulted in above mentioned error.

Renaming kunden.php to kundenseite.php resolved the problem, as apache had nothing left to negotiate!

THX to Ben for this post, it pointed my the right direction - Very helpful!

1 Comments

Thanks a million Ben!

I don't want to think about the time I'd have lost if this post didn't pop in my google search !!

And so well explained !

Thanks again!

John.

15,880 Comments

@Jonathan,

No problem! As someone [me] who is relatively new to Apache, it's super powerful, but definitely throws a number of curve-balls if the configuration is not quite right! I know enough to get things done; but, I'd love to have a better handle on the Web Server layer so that I could tap into even more of the power.

1 Comments

Very often when I "google" a problem, your posts are first to appear. More often than not, you have a solution. Thank you for posting your struggles to help those of us who have less tolerance to struggling. ;-)

1 Comments

Thanks so much for this. I just did a fresh install of ubuntu 12.10 and have almost gotten my system to where I want it to be only try to login to one of my dev sites to get this. Its strange though that I should be getting this error as having Multiviews has never caused me any problems. Anyway off to clock some billable hours :)

1 Comments

Thank you!
Just put this line in my Wordpress .htaccess:

Options -MultiViews

Now I can access both different pages: /page and /page.php

3 Comments

Hi Ben,

I had a similar error and was confused why, in development everything worked fine yet on my new testing server, all requests other than the home page failed. Thanks for the link.

I had exactly the same issue. Now to find out what mod was enabled on my dev box, that wasn't on my testing box.

Matt

1 Comments

Thank you VERY much! I was tearing my hair out on this one. We have our site set up to redirect 404s to our homepage. It was working on ANY other URL I entered that was bogus, but this ONE that was legit was throwing an immediate 404, not even running my site code. I knew it had to be Apache but had no idea what the errors meant. You saved me hours, thank you!!

1 Comments

I just wanted to thank you for this post. I was trying to use Apache to host a Keepass2 database and was unable to save until I removed MultiViews.

I must have looked though a dozen other websites before this one, and tried many other possible solutions! So simple in the end...

1 Comments

Thank you, for your information. I was searching for this solution over for 2 weeks. I could find it in Russian web internet, but there is it. Great, IT WORKS!!!

1 Comments

This worked for me:

You can remove MultiViews although the purpose is to speed up server processing.

So if you have www.domain.com/index
its naturally going to look for index.* (html,htm etc)
php is not considered a default in this instance until you tell the server to look for it.

So yes you can get round this by omitting the Multiviews.

Alternatively you could make sure they are included in your default mime.typesconfiguration
On Linux is located
/etc/mime.types and uncomment the lines that refer to php

IE - remove the comment hash # from these lines
application/x-httpd-php phtml pht php
application/x-httpd-php-source phps
application/x-httpd-php3 php3
application/x-httpd-php3-preprocessed php3p
application/x-httpd-php4 php4
application/x-httpd-php5 php5

If you do not have access to this file or are on shared hosting, you can add them to you .htaccess file in the root of your hosting.

Thanks

3 Comments

Thanks Ben, think you have probably just saved me the 2 hours it took yourself to figure this one out!!! Was getting the same on my Mac and was about to start pulling my hair out...

1 Comments

Mate, you just spent two hour,
I was working in a day and spent whole day and end of day, I removed every thing in the .htacess. but your topic really help and Next time I like to search and found some one like you who got such experiences and tell the solution.

1 Comments

Very useful thanks !

I spent almost an entire day trying to figure out why my route didn't work, until I find this post.

1 Comments

This post saved me much wailing and gnashing of teeth. Never come across it before somehow, I must have copy/pasted some default config. Thanks for taking the time to write it up.

1 Comments

Thank you sir!! I've been banging my head over this for hours. I went as far as to set 'AllowOverride All' in every Apache configuration file I could dig up on my server in an attempt to solve the 404 errors. After I undid all my changes and simply removed MultiViews from the sites-enabled configuration file, everything works! I completely agree on your point about enabling options that we don't understand, especially since the only reason I had MultiViews in there was that I saw it in a couple examples online. It's hard to focus on Apache2 server management when my primary purpose is to prototype a website on a local server before it goes live, but this problem goes to show that I should spend some time learning about the backend before going back into web development. Again, THANK YOU!!

3 Comments

Been fighting with getting my dev environment set up on my Mac and once again the great Ben Nadel and his blog come to the rescue to fix my only remaining issue and this time it wasn't even CFML related!!! Thanks Ben.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel