Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at Scotch On The Rocks (SOTR) 2011 (Edinburgh) with:

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

Posted by Ben Nadel
Tags: ColdFusion, Work

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.



Reader 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.

Reply to this Comment

@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 :)

Reply to this Comment

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.

Reply to this Comment

@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!

Reply to this Comment

@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.

Reply to this Comment

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 ?

Reply to this Comment

@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.

Reply to this Comment

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.

Reply to this Comment

@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.

Reply to this Comment

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.

Reply to this Comment

@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.

Reply to this Comment

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.

Reply to this Comment

@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!

Reply to this Comment

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!

Reply to this Comment

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.

Reply to this Comment

@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.

Reply to this Comment

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. ;-)

Reply to this Comment

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 :)

Reply to this Comment

Thank you!
Same problem, googled the error.log-message, first hit: your straightforward blog entry. :-)

Reply to this Comment

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

  • Options -MultiViews

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

Reply to this Comment

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

Reply to this Comment

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!!

Reply to this Comment

I'm glad this is helping people! It's a shame when little config issues like this will wastes HOURS of time!

Reply to this Comment

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...

Reply to this Comment

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!!!

Reply to this Comment

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

Reply to this Comment

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...

Reply to this Comment

Post A Comment

?
You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.