diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java
index cc37c2bf8b1f94d77a08a74c0e8ea9aa04b1f7f1..b35fc761755168c6d485a23a99da10cf9345dd9d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java
@@ -46,6 +46,7 @@
 import java.io.File;
 
 import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.RepositoryTestCase;
 
 public class DirCacheBasicTest extends RepositoryTestCase {
@@ -176,8 +177,10 @@ public void testBuildThenClear() throws Exception {
 
 		final String[] paths = { "a.", "a.b", "a/b", "a0b" };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 
 		final DirCacheBuilder b = dc.builder();
 		for (int i = 0; i < ents.length; i++)
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java
index fe02a1b23ea1c464a194f562b5cf11dbd4816b90..e919e41f4d947338d74bbb091404367a5d91cb83 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Google Inc.
+ * Copyright (C) 2008-2009, Google Inc.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -65,6 +65,20 @@ public void testBuildEmpty() throws Exception {
 		}
 	}
 
+	public void testBuildRejectsUnsetFileMode() throws Exception {
+		final DirCache dc = DirCache.newInCore();
+		final DirCacheBuilder b = dc.builder();
+		assertNotNull(b);
+
+		final DirCacheEntry e = new DirCacheEntry("a");
+		assertEquals(0, e.getRawMode());
+		try {
+			b.add(e);
+		} catch (IllegalArgumentException err) {
+			assertEquals("FileMode not set for path a", err.getMessage());
+		}
+	}
+
 	public void testBuildOneFile_FinishWriteCommit() throws Exception {
 		final String path = "a-file-path";
 		final FileMode mode = FileMode.REGULAR_FILE;
@@ -168,6 +182,7 @@ public void testFindSingleFile() throws Exception {
 		assertNotNull(b);
 
 		final DirCacheEntry entOrig = new DirCacheEntry(path);
+		entOrig.setFileMode(FileMode.REGULAR_FILE);
 		assertNotSame(path, entOrig.getPathString());
 		assertEquals(path, entOrig.getPathString());
 		b.add(entOrig);
@@ -191,8 +206,10 @@ public void testAdd_InGitSortOrder() throws Exception {
 
 		final String[] paths = { "a.", "a.b", "a/b", "a0b" };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 
 		final DirCacheBuilder b = dc.builder();
 		for (int i = 0; i < ents.length; i++)
@@ -213,8 +230,10 @@ public void testAdd_ReverseGitSortOrder() throws Exception {
 
 		final String[] paths = { "a.", "a.b", "a/b", "a0b" };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 
 		final DirCacheBuilder b = dc.builder();
 		for (int i = ents.length - 1; i >= 0; i--)
@@ -235,8 +254,10 @@ public void testBuilderClear() throws Exception {
 
 		final String[] paths = { "a.", "a.b", "a/b", "a0b" };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 		{
 			final DirCacheBuilder b = dc.builder();
 			for (int i = 0; i < ents.length; i++)
diff --git a/org.spearce.jgit.test/tst/org/spearce/jgit/dircache/DirCacheEntryTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java
similarity index 75%
rename from org.spearce.jgit.test/tst/org/spearce/jgit/dircache/DirCacheEntryTest.java
rename to org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java
index fa035d3327a43c30ef9e80b8f1fb96d1fa17e8dd..446fd706015ad35793d5e8a4b406d80377164d1d 100644
--- a/org.spearce.jgit.test/tst/org/spearce/jgit/dircache/DirCacheEntryTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheEntryTest.java
@@ -41,11 +41,12 @@
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-package org.spearce.jgit.dircache;
+package org.eclipse.jgit.dircache;
 
 import junit.framework.TestCase;
 
-import org.spearce.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
 
 public class DirCacheEntryTest extends TestCase {
 	public void testIsValidPath() {
@@ -118,4 +119,40 @@ public void testCreate_ByStringPathAndStage() {
 			assertEquals("Invalid stage 4 for path a", err.getMessage());
 		}
 	}
+
+	public void testSetFileMode() {
+		final DirCacheEntry e = new DirCacheEntry("a");
+
+		assertEquals(0, e.getRawMode());
+
+		e.setFileMode(FileMode.REGULAR_FILE);
+		assertSame(FileMode.REGULAR_FILE, e.getFileMode());
+		assertEquals(FileMode.REGULAR_FILE.getBits(), e.getRawMode());
+
+		e.setFileMode(FileMode.EXECUTABLE_FILE);
+		assertSame(FileMode.EXECUTABLE_FILE, e.getFileMode());
+		assertEquals(FileMode.EXECUTABLE_FILE.getBits(), e.getRawMode());
+
+		e.setFileMode(FileMode.SYMLINK);
+		assertSame(FileMode.SYMLINK, e.getFileMode());
+		assertEquals(FileMode.SYMLINK.getBits(), e.getRawMode());
+
+		e.setFileMode(FileMode.GITLINK);
+		assertSame(FileMode.GITLINK, e.getFileMode());
+		assertEquals(FileMode.GITLINK.getBits(), e.getRawMode());
+
+		try {
+			e.setFileMode(FileMode.MISSING);
+			fail("incorrectly accepted FileMode.MISSING");
+		} catch (IllegalArgumentException err) {
+			assertEquals("Invalid mode 0 for path a", err.getMessage());
+		}
+
+		try {
+			e.setFileMode(FileMode.TREE);
+			fail("incorrectly accepted FileMode.TREE");
+		} catch (IllegalArgumentException err) {
+			assertEquals("Invalid mode 40000 for path a", err.getMessage());
+		}
+	}
 }
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java
index cdc659a21c923423d673ee630c942ce3a5967081..d5a632c48cbc36498e594d9885581620a8a72097 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Google Inc.
+ * Copyright (C) 2008-2009, Google Inc.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -43,6 +43,7 @@
 
 package org.eclipse.jgit.dircache;
 
+import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.RepositoryTestCase;
 
 public class DirCacheFindTest extends RepositoryTestCase {
@@ -51,8 +52,10 @@ public void testEntriesWithin() throws Exception {
 
 		final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 		final int aFirst = 1;
 		final int aLast = 3;
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
index db9f684fed4a970ef36137b89040dde5d2fbb4b0..efea117388f714d395ccf759e8976966265a247d 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Google Inc.
+ * Copyright (C) 2008-2009, Google Inc.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -74,8 +74,10 @@ public void testNoSubtree_NoTreeWalk() throws Exception {
 
 		final String[] paths = { "a.", "a0b" };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 
 		final DirCacheBuilder b = dc.builder();
 		for (int i = 0; i < ents.length; i++)
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java
index ceaadf97b63c2cc3cbdf95ed388853ecb7f81775..0926ab9899c2618204ebc31cbd709808cc209456 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Google Inc.
+ * Copyright (C) 2008-2009, Google Inc.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -46,6 +46,7 @@
 import java.io.IOException;
 
 import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.RepositoryTestCase;
 
 public class DirCacheLargePathTest extends RepositoryTestCase {
@@ -76,6 +77,10 @@ private void testLongPath(final int len) throws CorruptObjectException,
 
 		final DirCacheEntry longEnt = new DirCacheEntry(longPath);
 		final DirCacheEntry shortEnt = new DirCacheEntry(shortPath);
+
+		longEnt.setFileMode(FileMode.REGULAR_FILE);
+		shortEnt.setFileMode(FileMode.REGULAR_FILE);
+
 		assertEquals(longPath, longEnt.getPathString());
 		assertEquals(shortPath, shortEnt.getPathString());
 
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java
index f74a35cd35bdb462d743b739fdc7bd70132f8afd..8345c5d83dada2c2c0621540ea22016468b3f12b 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Google Inc.
+ * Copyright (C) 2008-2009, Google Inc.
  * and other copyright owners as documented in the project's IP log.
  *
  * This program and the accompanying materials are made available
@@ -46,6 +46,7 @@
 import java.io.IOException;
 
 import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.RepositoryTestCase;
 
 public class DirCacheTreeTest extends RepositoryTestCase {
@@ -81,8 +82,10 @@ public void testSingleSubtree() throws Exception {
 
 		final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 		final int aFirst = 1;
 		final int aLast = 3;
 
@@ -116,8 +119,10 @@ public void testTwoLevelSubtree() throws Exception {
 
 		final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 		final int aFirst = 1;
 		final int aLast = 4;
 		final int acFirst = 2;
@@ -173,8 +178,10 @@ public void testWriteReadTree() throws CorruptObjectException, IOException {
 		final String B = String.format("b%2000s", "b");
 		final String[] paths = { A + ".", A + "." + B, A + "/" + B, A + "0" + B };
 		final DirCacheEntry[] ents = new DirCacheEntry[paths.length];
-		for (int i = 0; i < paths.length; i++)
+		for (int i = 0; i < paths.length; i++) {
 			ents[i] = new DirCacheEntry(paths[i]);
+			ents[i].setFileMode(FileMode.REGULAR_FILE);
+		}
 
 		final DirCacheBuilder b = dc.builder();
 		for (int i = 0; i < ents.length; i++)
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java
index f294f5cf515def98e0325c1cd6cb86d7fd0203ae..69f5444c643b09451d0b976f13ae74faee3183a3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java
@@ -48,7 +48,6 @@
 import java.util.Arrays;
 
 import org.eclipse.jgit.lib.AnyObjectId;
-import org.eclipse.jgit.lib.FileMode;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.WindowCursor;
 import org.eclipse.jgit.treewalk.AbstractTreeIterator;
@@ -97,8 +96,13 @@ protected DirCacheBuilder(final DirCache dc, final int ecnt) {
 	 *
 	 * @param newEntry
 	 *            the new entry to add.
+	 * @throws IllegalArgumentException
+	 *             If the FileMode of the entry was not set by the caller.
 	 */
 	public void add(final DirCacheEntry newEntry) {
+		if (newEntry.getRawMode() == 0)
+			throw new IllegalArgumentException("FileMode not set for path "
+					+ newEntry.getPathString());
 		beforeAdd(newEntry);
 		fastAdd(newEntry);
 	}
@@ -194,8 +198,6 @@ public void finish() {
 	}
 
 	private void beforeAdd(final DirCacheEntry newEntry) {
-		if (FileMode.TREE.equals(newEntry.getRawMode()))
-			throw bad(newEntry, "Adding subtree not allowed");
 		if (sorted && entryCnt > 0) {
 			final DirCacheEntry lastEntry = entries[entryCnt - 1];
 			final int cr = DirCache.cmp(lastEntry, newEntry);
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java
index 1ad8e355d5ae399c40e2ee04d95b38b2e75739db..85ad8b4d790119a6a888fdc1bc482dd8041af319 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, Google Inc.
+ * Copyright (C) 2008-2009, Google Inc.
  * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  * and other copyright owners as documented in the project's IP log.
  *
@@ -145,11 +145,16 @@ private void applyEdits() {
 			}
 
 			final DirCacheEntry ent;
-			if (missing)
+			if (missing) {
 				ent = new DirCacheEntry(e.path);
-			else
+				e.apply(ent);
+				if (ent.getRawMode() == 0)
+					throw new IllegalArgumentException("FileMode not set"
+							+ " for path " + ent.getPathString());							
+			} else {
 				ent = cache.getEntry(eIdx);
-			e.apply(ent);
+				e.apply(ent);
+			}
 			fastAdd(ent);
 		}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
index eed33401d510780de69118cc047f4e5d4b77fdab..415de095b2a1fda56dc8f81e706bf1ed49a04b19 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
@@ -388,8 +388,18 @@ public FileMode getFileMode() {
 	 *
 	 * @param mode
 	 *            the new mode constant.
+	 * @throws IllegalArgumentException
+	 *             If {@code mode} is {@link FileMode#MISSING},
+	 *             {@link FileMode#TREE}, or any other type code not permitted
+	 *             in a tree object.
 	 */
 	public void setFileMode(final FileMode mode) {
+		switch (mode.getBits() & FileMode.TYPE_MASK) {
+		case FileMode.TYPE_MISSING:
+		case FileMode.TYPE_TREE:
+			throw new IllegalArgumentException("Invalid mode " + mode
+					+ " for path " + getPathString());
+		}
 		NB.encodeInt32(info, infoOffset + P_MODE, mode.getBits());
 	}
 
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
index fc29aa71b85b054352c93e176b5c420965aaa883..144b1a6cfc4b18766550c5f619a933e0b0889340 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheTree.java
@@ -382,10 +382,6 @@ private int computeSize(final DirCacheEntry[] cache, int cIdx,
 			}
 
 			final FileMode mode = e.getFileMode();
-			if (mode.getObjectType() == Constants.OBJ_BAD)
-				throw new IllegalStateException("Entry \"" + e.getPathString()
-						+ "\" has incorrect mode set up.");
-
 			size += mode.copyToLength();
 			size += ep.length - pathOffset;
 			size += OBJECT_ID_LENGTH + 2;