I have been developing websites and web applications for more than 15 years now and I wanted to list the top 10 situations where I spent (or wasted?) a lot of time debugging or managing a situation where the root cause was tricky (or stupid?).


10. Animated GIF, Flash

All those proprietary formats were the only way to do some simple things like copy-to-clipboard, upload files in an interactive way or play a video.

Thank god AJAX, HTML5, CSS3 and JavaScript frameworks are now there to help. Now you can cut/copy text easily using clipboard.js, forget about Flash and its daily security update to play videos in pure HTML5, simply upload a file with drag and drop and progress bar in HTML5 and AJAX.

9. Internet Explorer

Yes, that’s right, just “Internet Explorer”. I don’t need to be specific, this web-browser has been a pain in the arse for any web developer due to its proprietary way of (poorly) doing things which required special pieces of code to render pages properly or run JavaScript code without errors. You would end up with crap code like this:

<!--[if !IE 6]><!-->
<link rel="stylesheet" type="text/css" media="screen, projection" href="REGULAR-STYLESHEET.css" />

<!--[if gte IE 7]>
<link rel="stylesheet" type="text/css" media="screen, projection" href="REGULAR-STYLESHEET.css" />

<!--[if lte IE 6]>
<link rel="stylesheet" type="text/css" media="screen, projection" href="http://universal-ie6-css.googlecode.com/files/ie6.0.3.css" />

If you really enjoy this, you can find some more IE CSS hacks here.

8. URL rewriting rules behaviour in .htaccess

The issue is well explained in the stackoverflow post here: mod_rewrite loops even with L flag. The reason is that you need to understand well the behaviour of mod_rewrite with Apache:

The [L] flag DOES work in .htaccess files. It tells the rewrite module to skip all of the following rules in that particular .htaccess file. It does its job, Apache rewrites the url and exits the .htaccess file.

However, at the end of the .htaccess file if the request url has been rewritten, the whole url matching process starts again with the new url.

So you need to be aware of the logic of your file, as your URLs might go several times into the mod_rewrite process until they are not rewritten anymore.

7. Facebook API light-speed depreciation


Facebook has been releasing updates of its API three times per year for the past couple of years (see Graph API changelog). It is great for all innovations this allows but this also means there are potentially three code-breaking events to manage every year for web developers.

This issue is not going away anytime soon and does not apply only to Facebook APIs, but also to all multiple web development frameworks and third-party modules we can use to bootstrap a website quickly.

Today’s challenge is to bet on the right horse when choosing a framework to start a new web project. It’s the same as VHS vs Betamax, the HD-DVD vs BluRay or the 4G WiMAX vs 4G LTE, but this time for coders: pick the wrong one and you will have to migrate your entire project to a new technology very soon.

Check out for example the multiple articles about choosing Angular vs React:

I personally quite like ReactJS although I have not produced anything viable with it at this stage.

6. UTF-8 file format with BOM and header() command

UTF-8 (UCS transformation format 8 bits) is probably the most used character encoding format nowadays as it supports many languages and scripts. Standard encoding of UTF-8 files comes with a BOM (Byte Order Mark) at the beginning of the file. It is a zero-width no-break space, invisible for the user, it is actually not really useful for UTF-8 but is for UTF-16 or UTF-32.

Because of this extra character at the beginning of the file, some php files will face issues when the header() function is used, for instance to redirect a page  using header(“destination.php”); or to specify the type of a file to download with header(‘Content-Type: application/pdf’); . A fatal error will be thrown as some content (the BOM) will have been already sent to the browser before all headers information are set:

Warning: Cannot modify header information – headers already sent by (output started at C:\www\index.php:1) in C:\www\index.php on line 3

The solution is to use a text editor that supports encoding in UTF-8 without BOM. You can use Notepad++ for instance. Note that in the latest versions of Notepad++, the format without BOM is just called “UTF-8”:


5. Root folder path silently changed by hosting company

That happens for example if you were hosted on /var/mywebsite, and, during a migration, your hosting company decided to move you on /home/mywebsite. If you have scripts for managing file uploads or read/write, they will probably break and you should check this home path as a first culprit.

That works also with the address of your mysql database.

When I was on mysql50-31.perso.ovh.net for some time and then suddenly moved to mysql55-122.perso.ovh.net without warning, it took me some time to figure it out. Good thing is that OVH now has aliases using db-name.mysql.db so that the problem does not happen anymore.

4. Cached CSS and JS files due to a forgotten .htaccess rule

Activation of browser caching with .htaccess is a great way to improve browsing experience and increase SEO ranking, but don’t forget you did it when you are developing your website. For instance check out the rule:

# 1 Month for most static assets
<filesMatch ".(css|jpg|jpeg|png|gif|js|ico)$">
Header set Cache-Control "max-age=2592000, public"

All files matching the pattern will be cached by the browser for one month (2592000 seconds). This means you will not see a change you may do in your stylesheet (CSS) or your JavaScript (JS) until 30 days. Two solutions:

  • when testing changes, disable browser caching on your own browser, or empty your cache every time (e.g. in Firefox, right click on your website in the history and choose “Forget Site”).
  • use name versioning for your files, for instance call your style sheet with a dummy argument (?v=20170511) which you will change every time you do an update, this will also force all your visitors to see the change immediately: <link rel="stylesheet" type="text/css" href="style.css?v=20170511" />
3. HSTS header used to force SSL

HTTP Strict Transport Security (HSTS) is a great protocol aimed at fighting against man-in-the-middle attacked where a hacker would create a fake website to capture someone credentials. This protocol has a special header which will tell all web browsers to forbid access to the website without SSL as follows:

Enable HSTS

<?php header("strict-transport-security: max-age=10886400");

Disable HSTS

<?php header("strict-transport-security: max-age=0");

This way, a MITM attack will mostly fail as it won’t be able to use http, and https access to the site will display an big red invalid certificate error to the visitor and stop there.

Be careful with this, as if for some reason your https access to your website is broken, your visitors will not be able to access your website until the expiration date defined and you will not be able to revoke the expiration date as well. The only solution for your visitors would be to clear the HSTS flag in their browser which is complicated.

2. AdBlockPlus stopping a script or an image detected as an ad

This issue drove me crazy: the AdBlockPlus plugin on my web browser was blocking pictures on my web server which were stored in the folder /pictures/ads. But, these pictures were not for annoying publicity but to illustrate classifieds advertising (hence the name of the folder on the web server):

AdBlockPlus had this synchronization done with “EasyList” which one day decided to add /pictures/ads/* as a filter to block advertising content, and unfortunately hit a false positive on my website. Conclusion: avoid the word “ad” in folder/file names.

1. And the winner is: Browser storing a permanent redirection (301)

Be careful when you push apermanent redirection with your .htaccess or the header() function in php. Consider for example this (dangerous) rule:

RewriteRule ^(.*).php$ /$1.htm [R=301,L]

Even after you remove it from your code, your browser will remember it and if you forgot it, you will certainly end up going crazy trying to understand why your change done in the code does not appear on the server.

In Firefox, you need to go to the history, find your website in the list and right-click to perform the “Forget about this site” action as shown below: