Thursday, February 01, 2007

IE's Unknown Runtime Error When Using innerHTML

IE never fails to surprise me. Look at the following code for example.

<html>
<body>
<p id="someId"></p>
<script type="text/javascript">
document.getElementById("someId").innerHTML = "<li>Some content</li>";
</script>
</body>
</html>

This code has surprising results in Internet Explorer and Firefox, and I haven't found a decent explanation on the Internet of what exactly happens, so I'm posting this out of utter surprise.

First thing you'd notice is that someId is a paragraph (p) tag. Secondly we are inserting a list item (li) into this paragraph, without having a unordered list (ul) as a parent element of this list item. If you are really the kind of markup nazi that I am, you'll notice that the p tag doesn't allow any block-level tags within it, and both LI and UL are block level tags, which is not permitted by the W3C rules.

So, how do browsers react to this?

Firefox does some code cleanup (I guess), and renders what looks and behaves like a list item, complete with a bullet and stuff. (Interestingly, it assumes that it is an unordered list and not an ordered list. Wonder why that's the case.)

IE's JavaScript on the other hand breaks with an "Unknown runtime error"! I agree completely that this is not a good error message at all, but really, IE is enforcing correct W3C block/inline tag recommendations here - something Firefox is not doing. To demonstrate this, change the p to a ul, and the code will work in IE.

IE's not 100% percent correct, though. It looks like it only enforces block/inline tags and not really tag semantics. Which means if you change the p to div, the code will execute correctly, since the div element allows other block-level tags within it. So, IE doesn't seem to be perfect, but seems to be kinda stricter than Firefox. Which may or may not be a good thing.

71 comments:

Gravecat said...

I've noticed that IE seems to have trouble with a lot of code that Firefox tends to just take for granted. Not Javascript, since I don't really deal with that much myself, but it's a common event to have some CSS that works perfectly in other browsers, then IE balks and refuses to render it correctly.

I always used to think that IE was too lax with its HTML standards, though. Now it just seems like it's far too strict... it's just that the standards it sticks to aren't always the same as everyone else's.

silentl said...

I also get this error when I try to insert a form within another form.

<html>
<body>
<form>
<div id="someId"></div>
</form>
<script type="text/javascript">
document.getElementById("someId").innerHTML =
"<form>Some content</from>";
</script>
</body>
</html>

Rakesh Pai said...

That's very interesting. Though I know that nested form tags are not allowed according to the HTML specs, IE is the last browser I would expect to enforce it.

voracity said...

Great, except I think IE's behaviour is then wrong when doing this:

<html>
    <head>
        <style>
            #testInline { display: inline; }
        </style>
    </head>
    <body>
        <p id="someId"></p>
        <script type="text/javascript">
            document.getElementById("someId").innerHTML =
"<div id='testInline'>Some content</div>";
        </script>
    </body>
</html>

Rakesh Pai said...

@voracity:

That behavior is not wrong. Markup, as defined in the specs, are they way they are. Some elements are block, and some others are inline. A div is a block element, and nothing can change that.

You can use CSS to *render* a block element as an inline element. However, that doesn't change the way the browser handles block elements and their related behaviors - only the way it is rendered.

In other words, a <div style="display: inline;">blah</div> is not the same as a <span>blah</span>, even though it is rendered the same.

voracity said...

(Sorry for the late reply.)

Ok, I guess I'm biased here, because I believe you should be allowed to insert whatever element you want into whatever other element you want. How that renders or behaves, or what it means, should be an entirely separate issue.

According to the relevant parts of the HTML spec, you are almost certainly correct:
HTML 4.01: 7.5.3 Block-level and inline elements
HTML 4.01: B.1 Notes on invalid documents
But I don't think the spec authors had things like well-formed xml, javascript insertions, run-ins/compacts and especially inline-blocks/inline-tables in mind. The XHTML spec only has this to say:
HTML 4.01: B. Element Prohibitions
Which seems fairly permissive, except the DTD still only allows inline children for paragraphs.

The reason I came across this issue is because of excanvas. Because excanvas uses vml:group elements (which seem to be block-level, the w3 tech note isn't clear), you cannot insert a canvas into a paragraph in IE. Maybe vml:group should have been inline or inline-block, but I don't see any reason why they can't just be defined as block-level elements.

Anyway, there are other problem cases as well. For example, numbered equations are blocks, but should absolutely be considered part of a paragraph (as they are in LaTeX). Similarly, blockquotes are, as their name betrays, blocks, and there are plenty of cases where they too should be considered part of a paragraph. Indeed, even lists are often part of a paragraph.

Ultimately, to my mind, there is no semantic difference between block-level and inline-level elements. The only difference is presentational. Indeed, the HTML spec admits as much in defining DIV and SPAN elements.

Finally, to round things off, IE's behaviour is almost certainly an unintentional consequence of the way it parses or internally represents documents. For example, IE permits the following, which even more clearly violates the block-level/inline-level rule:

<html>
    <head>
        <style>
            #someId { display: block; }
            #testInline { display: inline; }
        </style>
    </head>
    <body>
        <span id="someId"></span>
        <script type="text/javascript">
            document.getElementById("someId").innerHTML =
"<div id='testInline'>Some content</div>";
        </script>
    </body>
</html>

PatriotB said...

I just came across this same error, while attempting to do the same thing not via script but from a C++ program. Using the debugging symbols available for IE, I was able to step deep into the code (well, the names of the functions at least) that runs when you set innerHTML.

It ends up calling a function called "ValidateElements" which, interestingly enough is publicly documented at http://msdn.microsoft.com/workshop/browser/mshtml/reference/IFaces/MarkupServices2/ValidateElements.asp.

The function indeed seems to (try to) look for any invalid HTML, and reject it. In my case, my innerHTML was "[p][hr][/p]" and it failed. (tags adjusted for Blogger)


Voracity brought up XML/XHTML. However, in this case, XML/XHTML has nothing to do with anything; HTML is a separate specification with its own rules, and MSHTML (IE's HTML parser) is only an HTML parser. It makes no claim to be an XML parser or to support XHTML.

It is interesting that, in this case, IE is strictly adhering to a standard when in many other places it doesn't. However, those "other places" are primarily CSS-related; the core HTML implementation is pretty solid.

So why is innerHTML so strict? If you load a webpage with the "bad" HTML in it, IE will display it just fine, so why can't innerHTML adapt? Only Microsoft knows.

But I guess we should be thankful that the parser isn't so strict -- I bet the parser is clamoring to throw errors for all sorts of invalid things it finds in documents, but doesn't, to avoid error messages showing up for the vast majority of web sites.

Another thing that's important to keep in mind, is that innerHTML is not part of any standard. IE was the first to have it, and thus its behavior (including unwanted errors) is the closest thing to a standard there is. Comparing its behavior to how Firefox does it isn't valid, because Firefox is the one copying IE. It's just that they didn't copy the strictness, apparently.

Rakesh Pai said...

Thanks patriotb for taking the time for giving that explanation. I agree completely with you.

Voracity, unlike what you have said, the CSS doesn't alter the semantics of the tags. So, adding CSS to make the tags block or inline won't change how the HTML parser loads the markup.

shobitha kishan said...

HI,

I faced the similar problem Could you please tell me the alternate solutions which can work both in IE and fire fox??

Thanks,

Anonymous said...

We are running into the same issue now. We're trying to innerHTML an external blob of HTML into a div with Ajax. In Firefox we get errors in the console about why the HTML we're trying to insert is bad. (It is bad; we can't control it for reasons too stupid and frustrating to explain)

In IE it just silently refuses to do anything.

Since we can't fix the HTML we're getting (without all sorts of awful parsing) it looks like we're pretty much screwed.

Rakesh Pai said...

Shobitha & Anonymous:

I don't think there's any easy alternate solution. If you are going to insert content using JavaScript, these are the problems you are going to face.

One solution would be to parse the content to ensure that tags are well formed and well nested. This could be done in JavaScript, but is very tedious. If you can do something on the server, you could use something like HTML Tidy (PHP, I believe - there should be other implementations) to clean up the markup. If the content is coming from a third party, you should consider setting up a proxy on your server to clean up the markup. It's the only way I know. The last ditch effort (and what I did when I faced this problem) is to let the third party know why they shouldn't write bad markup, and get them to fix their content.

Now, only if people were validating their markup...

Anonymous said...

I had the same problem with IE.

The reason was that the name of the javascript function was the same as the name of the div from witch I wanted to change the InnerHTML.

Try to give them different names.

Unga said...

I had a similar problem with a function that was appending content to the document. I was creating a new <p> element to contain the text and appending the new element to the document body. I encountered the IE Unknown Runtime Error when the text to insert contained an <hr> tag. FireFox did not throw an error. After reading this post, I changed the new element from <p> to <div> and as one would expect, the problem disappeared. Thanks!

The improved function is as follows:

function documentAppend(eleText,eleTag) {
var fname="documentAppend()";
if ( this.debug ) { alert( fname + "\n\n eleTag=" + eleTag + "\n\n eleText=" + eleText );}
try {
// sanity check
if ( eleText==undefined || !eleText ){eleText=" ";} //  
// note: W3C rules state that the p tag doesn't allow any block-level tags within it, and both LI and UL are block level tags, so lets use a <div> instead of a <p>
if ( eleTag==undefined || !eleTag ){eleTag="div";}

// create and populate the new element
var theNewEle = document.createElement(eleTag);
// NOTE: want to preserve embedded HTML Tags that are embedded into the eleText. createTextNode() does not do this.
//var theNewEleText = document.createTextNode(eleText);
//theNewEle.appendChild(theNewEleText);
theNewEle.innerHTML = eleText;

// append the new element to the end of the document
document.body.appendChild(theNewEle);
}
catch(ex)
{
alert(fname + "\n\n Error occured: " + ex.message);
}
}

Anonymous said...

If you want to completely break IE7's use of innerHTML, try removing the doctype definition.

Danno said...

I was struggling with this runtime error, and after half an hour, I realised that the innerHTML was trying to change the P tag.. I changed it to div, and no more error.

Anonymous said...

Thanks a bunch. This really helped me. I got this error trying to set the innerHTML of a DIV through jscript, that before the script was run showed a nice animated wait gif. Setting the innerHTML dynamically revealed my original page wasnt well formed.

jordan said...

curious how you say "IE's not 100% percent correct, though. It looks like it only enforces block/inline tags and not really tag semantics." --
:) your opinion of ms is far too high.

ie is not 'enforcing' anything. these are just pure bugs you're running into.

innerhtml is particularly problematic, select elements, table elements especially.

container said...

I've had the same problem and after 4 hours of debugging It came out that innerHTML doesn't work with IE if you have hyperlink tag opened on the element you are filling html to.

Here the example code.

link


which happily returns: "line5: Unknown Runtime error"



And that is in IE7 as well.

[ok, it's 4 am here now. Am I missing something REALLY obvious now, because it just seems such a major ie BUG]

Rakesh Pai said...

@container:
That behavior of IE is right - HTML doesn't allow links to be nested.

@Jordan:
Trust me, I will be the first one to bash IE when they have genuine bugs, and I have vehemently done that before. However, innerHTML was MS's invention, so they get the benefit of doubt about how the behavior should work. Also, about the statement you quoted, that's still true. It's not the behavior everyone else has, but by no stretch of imagination is it wrong.

siam said...

I'm having the same exact problem, except I'm trying to include an image < img> inside of a < div> with innerHTML. I'm pretty sure < img> tags are allowed in < div>'s so, the whole thing about putting block elements inside of inline elements is irrelevant here I think.

There's something else IE is doing wrong. Please send a follow up if I'm wrong. I can share my code too if that helps, although it's basically the same as the original code posted here.

Anonymous said...

I found the best way to avoid IE errors when using innerHTML is to create a new div and swap them:

someHtml = 'Some Html Text';

oldDiv = document.getElementById('oldDivId');

newDiv = document.createElement(oldDiv.tagName);

newDiv.id = oldDiv.id;
newDiv.className = oldDiv.className;
newDiv.innerHTML = someHtml;

oldDiv.parentNode.replaceChild(newDiv, oldDiv);

Anonymous said...

Thanks everyone, I solved multiple problems based on this page (IE's innerHTML issues using the swap solution above, and the "function name matches element id" problem with IE).

I now hate IE more than RealPlayer.

Anonymous said...

WOW!!!!!!!!!!!
tank you sooooooooooo muuuuuuuuch...
i tried to blame microsoft for this kind of error.. damn ur so good... i mean u solved my problem instantly.. THANK YOU SO MUUUUCHHHHH....^_^

chrismitchellonline said...

Great article, thanks so much! woulda been chasing my tail for much longer with that wonderful "Unknown runtime error"

Was trying to add an ID to a table and update with js, not a good idea apparently.

Thanks again!

Pavan said...

thanks......works like a charm

Grateful said...

Thanks for the bit of info I found here. I was looking everywhere to see why IE was choking on my innerHTML. Didnt rwalize i had a form within a form till I found this.

Anonymous said...

and now the 1$ question : it works just fine with html in innerHtml, but what if the code added in innerHtml is javascript that needs to be executed?

Zack said...

"innerhtml is particularly problematic, select elements, table elements especially."

jordan - THANK YOU!

J E Carter II said...

Thanks, this was very helpful. In my case, innerHTML was failing against a div I had added to the form with createElement. The very end of the page had an unclose p just before the end of the form element. Eliminating that solved the problem.

This is consistent with PatriotB suspecting that ValidateObject is being more strict than the HTML parser. The page renders no problem, but makes for a broken DOM.

mark said...

Thanks for this. I've been trying to add a <tr> into a <table> using the table's innerHTML -- couldn't work out why IE wouldn't let me.

It's tabular data before any css specialists jump down my throat ;)

I've had to refactor the HTML to use <div>s and <span>s. Hacky, but at least it works now...

Anonymous said...

I've had the same problem and the issue was that I was trying to set the innerHTML on a TextBox Control that was rendered server side from ASP.NET.

Just changed this to textbox.value = 'value' instead and the message disappeared.

Rob C said...

Thanks so much - had been wondering what on earth 'unknown runtime error' could mean, and thanks to this post, I solved it (in this case, placing 'div' in 'p' was the problems...

Justin said...

You can put your divs inside tables and it'll work fine, but God help you if you try to use javascript to change their contents!

@mark: why don't use just use the insertRow/insertCell/appendChild methods to create your table?

Mangal Varshney said...

I am facing some problem in inserting CSS file + HTML using innerHTML.

I want to insert a .css file with html in div using innerHTML function. Html is
inserting but css is not working on html after inserting. sample code are
following. Code is working good in firefox but not working in IE7

<html>

<head>

<link href="1.css" rel="stylesheet" type="text/css">

</head>

<body>

<div id="someId" class="sid">Mangal</div>

<input type="button" onclick="test()">

<script type="text/javascript">

function test()

{

document.getElementById("someId").innerHTML = "<link href='2.css'
rel='stylesheet' type='text/css'><div class='testInline'>Some content</div>";

}

</script>

</body>

</html>


help me on this

Agush88 said...

gracias!! me salvaste la vida! estuve con ese problema un buen rato no sabia que era! gracias!!

en ingles:

thanks!! you saved my life!! i've been looking everywhere for that answer! it was driving me crazy! thanks again!

Sebastiaan said...

Well, the proposed solutions didn't help at fist... But after some trial and error I found that the innerHTML gave a conflict because of the appearance of an object with the same name as the id I was referring to. At first the name of the input field was the same as the id of the div tag. I added '_div' to the id, and it worked like a charm!

Code:
-----------------------------
<!-- javascript meta -->

function auto_fill(fill_type, string, field)
{

..

document.getElementById(field + '_div').innerHTML = output;
}

<!-- html -->
<input type="text" name="placement_field" value="" onkeypress="javascript: auto_fill('placement', this.value, this.name);"></input>
<div id="placement_field_div" class="input_field" style="display: none;">
<!-- Fill box for auto fill -->
</div>
-----------------------------

I hope I can save some people the useless hours I spend on this problem...

steinjak said...

Just lining up with everyone else bitten by this behaviour. It bit me when I was using one of my company's JS libraries to set up partial page rendering with AJAX, and some other developer wrote a fragment that contained a form. When this fragment was loaded into a portion of the page containing a form (ASP.NET webforms usually do...), IE fell on its face with the unknown error - and its debugger pointed me and my Visual Studio to line 5000-something in a generated JS sent by the ScriptService (sic!). It took me several hours of debugging on a Saturday to figure that one out...

peter_raganitsch said...

Thanks all for the inspiration.

I tried to replace a tables content, but couldn't figure out how IE would expect my code to be structured.

So I wrapped a div-tag around my table and replace this.

Works like a charme ;-)

Fincozmoz said...

Thank you for this! I was going crazy trying to ajax in the content within a table and got this error. When I wrapped the table within a div and returned the entire table it worked fine.

Anonymous said...

Awesome, Thanks :)

Avinash said...

Thanks for this post. I was having a similar issue that was driving me nuts. I do agree that the rules should be enforced but a friendlier message rather than "Unknown Exception" would be really useful. What I was trying to do was clear the contents of a table but apparently it doesn't like me feeding just a "" as its content, whereas it doesn't complain when rendering it in that manner initially. A CSS warning tool similar to the one in the Error console of Firefox would be welcome too. Cheers.

Floris said...

My Internet Browser has problems with the h1-tag.

I solved this by using font size = 1, was ok for me.

ethan said...

Uh... should be obvious but for anyone who's dealing with forms...
Please make sure that the innerHTML that ur injecting doesnt contain another "form" tag, or this error will occur also...
integration is really really evil... -_-''

janix said...

I had a similar error when trying to add a simple A HREF. I found that the problem was that I had an ANCHOR with the same NAME as a DIV ID elsewhere in the page. This code was outside the DIV I was altering.

Suggestion, look for any element that has the same NAME as another. You also have to make sure that no element has an ID that is the same as another element's NAME.

Josh Bodily said...

Thank you for the post. Apparently you can't use innerHTML on a tr even if you are putting in valid td tags. Doesn't make sense to me, but whatever.

Adam Lofting said...

Thanks for this post. I really wouldn't have guessed this and you saved me a lot of time before I started investigating other ideas!

Rajapandian said...

Hi,

If we want to insert form within form, we can use

var someHtml=HTMLTextHere;
someHtml=someHtml.replace(/<[//]{0,1}(form|Form)[^><]*>/g, "");
document.getElementById(divid).innerHTML = someHtml;

Rakesh Pai said...

@Rajapandian: Why would you want to have a form inside a form? I can't think of a use-case.

Chris said...

I found a solution!

First my problem was that I was trying to insert a form via innerHTML. Firefox was fine, IE was was producing the runtime error.

Well I narrowed it down to the form was causing the problem. I could insert the innerHTML without the form, but as soon as I added the "form" tag to the innerHTML, there was the damn runtime error.

Finally, I checked over my code and I had numerous forms that wern't closed ("/form"). As soon as I closed them all, my innerHTML form could be inserted! Seems like IE doesn't like open forms.

Flamming_Python said...

Mangal Varshney: Thank you very much for your code & insight!

Cerx said...

Form within a Form was killing me. Took a bit of looking to figure it out. Thanks.

Anonymous said...

Thanx buddy i solved big problem.
But i am not able to implement table in IE. So have you any idea please let me know your suggetions.

Anonymous said...

If using any <tr id='human1'> and want to hide it using innerHTML..(document.getElementById("human"+blogID).innerHTML = '';)then IE got the problem...shows unknown runtime error.

If someone use <div> may be you can solve the problem but have to keep in mind that other's div ID doesn't interfare with the div ID you are involved with.

For <tr... case use to hide with <td id='human1'>, the run time error vanishes. I was looking for a solution but I solved it by myself. I hope it helps someone.

Anonymous said...

Another cause of the "Unknown runtime error" is attempting to write to elements that are read-only in IE. These include most table tags, TR in particular. See http://support.microsoft.com/kb/239832 .Microsoft's workaround is to use the table object model instead.

Anonymous said...

thanks you help me to find that it's not working also with the , so I replace them with < p >< /p > and on onclick action...perfect :-)

6 hours to find this point !!!!

Mark Brodsky said...

I had this same problem with the "Unknown Runtime Error" in IE 8 - code worked fine in Firefox and Safari...

But, I was not illegally placing a block element into an inline or other element. I was simply updating the innerHTML of a SPAN within a surrounding DIV. So no problem, right?

Pulled my hair out trying to figure out what was happening until I thought maybe I was using a reserved keyword.... Sure enough - my SPAN ID was 'type'. I changed it to 'typer' and it all worked fine.

The funny thing about this is that it WAS working fine. Must have been a Windows update that caused it to suddenly fail.

Blog said...

Great post, and great discussions. I had a similar problem with "Unknown runtime error" from IE, FF and Chrome were just fine. Actually, FF is slutty.
My problem turned out be that a widget (dojo) included has a form tag, and the page itself has a form tag, so the nested form tags threw IE off.
Thanks guys!

Ryan said...

Just use jquery innerhtml

$(id).html('String');

saTya said...

For me I was generating a block containing single < form > and multiple nested 'div'.

Yes, the 'form' tag gave me the problem while assigning to 'innerHTML', so simply not using the 'form' tag resolved the issue in IE8 and IE9.

I always thought that IE was not strict in following standards as compared to FF, CHROME and SAFARI..

Well, I now know who is the BOSS..

JDSANS said...

Thanks so much. This information helped me debug my JavaScript in just five seconds.
Your a life saver

Mourya said...

swap the div element by creating a div element solved my problme.

Chim said...

looking for a solution that will work, look at what ryan said

use jquery's html() function

Thanks Ryan ;-)

Ramesh Karuppasamy said...

Its very helpful to us. thanks a lot...

Lacho said...

God bless you man, was fighting with this for several days until finally decided to paste the error in Google :)

This doesn't seem to happen in IE9, so even though it's basically enforcing a proper standard, they seem to acknowledge it as a bug.

Thanks again!

Anonymous said...

Thanks for this. Had a similar issue while writing a table via innerHTML. IE was throwing the same error. Removing the outer table fixed the issue.

Sourabh Nazarkar said...

Thanks a lot it works...i was using nested form tags tht causing problem..

Anonymous said...

I had this error when dynamically looking for content to replace some text, so re-formating would become very difficult.

The jQuery method of just using this.html(this.html.replace("word", ""); worked for me

Ajay Srinivasa said...

awesome :) this blog has helped me a lot

Anonymous said...

Very helpful...Had wasted 2 days to figure this issue and this blog resolved it within a second.Great Work :)

sirangeevi sabha said...

I've the problem It came out that sx:tabbedpanel doesn't work with IE.
that is couldn't load content:unknown run time error. how fix this plz help frnds.... in firefox and chrome wrkng fine.

haseeb anwar ul haq said...

I also encountered the same issue when things worked for me in Chrome, Firefox and Safari and I was unable to get through in IE8. Finally I managed to get my code working :)

Replace innerHTML with jquery html().

Visit the below link for example working perfect in IE 8

http://www.thesstech.com/youreditor?filename=dbadmin/5

ShareThis