Index: lucene/src/test/org/apache/lucene/index/TestIndexWriter.java
===================================================================
--- lucene/src/test/org/apache/lucene/index/TestIndexWriter.java	(revision 1188145)
+++ lucene/src/test/org/apache/lucene/index/TestIndexWriter.java	(working copy)
@@ -1096,6 +1096,33 @@
     reader.close();
     dir.close();
   }
+  
+  public void testEmptyFieldNameEmptyTerm() throws IOException {
+    Directory dir = newDirectory();
+    IndexWriter writer = new IndexWriter(dir, newIndexWriterConfig( TEST_VERSION_CURRENT, new MockAnalyzer(random)));
+    Document doc = new Document();
+    // TODO: why do we throw IAE: name and value cannot both be empty in Field ctor?!
+    doc.add(newField("", "", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("", "a", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("", "b", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    doc.add(newField("", "c", Field.Store.NO, Field.Index.NOT_ANALYZED));
+    writer.addDocument(doc);  
+    writer.close();
+    IndexReader reader = IndexReader.open(dir, true);
+    IndexReader subreader = SegmentReader.getOnlySegmentReader(reader);
+    TermEnum te = subreader.terms();
+    assertTrue(te.next());
+    assertEquals(new Term("", ""), te.term());
+    assertTrue(te.next());
+    assertEquals(new Term("", "a"), te.term());
+    assertTrue(te.next());
+    assertEquals(new Term("", "b"), te.term());
+    assertTrue(te.next());
+    assertEquals(new Term("", "c"), te.term());
+    assertFalse(te.next());
+    reader.close();
+    dir.close();
+  }
 
   private static final class MockIndexWriter extends IndexWriter {
 
Index: lucene/src/java/org/apache/lucene/index/SegmentTermEnum.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/SegmentTermEnum.java	(revision 1188145)
+++ lucene/src/java/org/apache/lucene/index/SegmentTermEnum.java	(working copy)
@@ -25,6 +25,7 @@
   FieldInfos fieldInfos;
   long size;
   long position = -1;
+  private boolean first = true;
 
   private TermBuffer termBuffer = new TermBuffer();
   private TermBuffer prevBuffer = new TermBuffer();
@@ -116,6 +117,7 @@
     termBuffer.set(t);
     prevBuffer.reset();
     termInfo.set(ti);
+    first = p == -1;
   }
 
   /** Increments the enumeration to the next element.  True if one exists.*/
@@ -163,6 +165,12 @@
   final int scanTo(Term term) throws IOException {
     scanBuffer.set(term);
     int count = 0;
+    if (first) {
+      // Always force initial next() in case term is Term("", "")
+      next();
+      first = false;
+      count++;
+    }
     while (scanBuffer.compareTo(termBuffer) > 0 && next()) {
       count++;
     }
Index: lucene/src/java/org/apache/lucene/index/TermInfosReader.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/TermInfosReader.java	(revision 1188145)
+++ lucene/src/java/org/apache/lucene/index/TermInfosReader.java	(working copy)
@@ -276,13 +276,7 @@
     if (enumerator.term() != null && term.compareTo(enumerator.term()) == 0) {
       ti = enumerator.termInfo();
       if (tiOrd == null) {
-        // LUCENE-3183: it's possible, if term is Term("",
-        // ""), for the STE to be incorrectly un-positioned
-        // after scan-to; work around this by not caching in
-        // this case:
-        if (enumerator.position >= 0) {
-          termsCache.put(cacheKey, new TermInfoAndOrd(ti, enumerator.position));
-        }
+        termsCache.put(cacheKey, new TermInfoAndOrd(ti, enumerator.position));
       } else {
         assert sameTermInfo(ti, tiOrd, enumerator);
         assert enumerator.position == tiOrd.termOrd;
Index: lucene/src/java/org/apache/lucene/index/TermInfosWriter.java
===================================================================
--- lucene/src/java/org/apache/lucene/index/TermInfosWriter.java	(revision 1188145)
+++ lucene/src/java/org/apache/lucene/index/TermInfosWriter.java	(working copy)
@@ -167,6 +167,11 @@
       if (ch1 != ch2)
         return ch1-ch2;
     }
+    if (utf16Result1.length == 0 && lastFieldNumber == -1) {
+      // If there is a field named "" (empty string) with a term text of "" (empty string) then we
+      // will get 0 on this comparison, yet, it's "OK". 
+      return -1;
+    }
     return utf16Result1.length - utf16Result2.length;
   }
 
Index: lucene/src/java/org/apache/lucene/document/Field.java
===================================================================
--- lucene/src/java/org/apache/lucene/document/Field.java	(revision 1188145)
+++ lucene/src/java/org/apache/lucene/document/Field.java	(working copy)
@@ -396,8 +396,6 @@
       throw new NullPointerException("name cannot be null");
     if (value == null)
       throw new NullPointerException("value cannot be null");
-    if (name.length() == 0 && value.length() == 0)
-      throw new IllegalArgumentException("name and value cannot both be empty");
     if (index == Index.NO && store == Store.NO)
       throw new IllegalArgumentException("it doesn't make sense to have a field that "
          + "is neither indexed nor stored");
