diff --git a/libinterp/corefcn/sub2ind.cc b/libinterp/corefcn/sub2ind.cc
index 8465a11..162ea89 100644
--- a/libinterp/corefcn/sub2ind.cc
+++ b/libinterp/corefcn/sub2ind.cc
@@ -134,9 +134,9 @@ linear_index = sub2ind ([3, 3], 2, 3)\n\
 
 # Test low index
 %!assert (sub2ind ([10 10 10], 1, 1, 1), 1)
-%!error <subscript indices> sub2ind ([10 10 10], 0, 1, 1)
-%!error <subscript indices> sub2ind ([10 10 10], 1, 0, 1)
-%!error <subscript indices> sub2ind ([10 10 10], 1, 1, 0)
+%!error <Accessing index 0> sub2ind ([10 10 10], 0, 1, 1)
+%!error <Accessing index 0> sub2ind ([10 10 10], 1, 0, 1)
+%!error <Accessing index 0> sub2ind ([10 10 10], 1, 1, 0)
 
 # Test high index
 %!assert (sub2ind ([10 10 10], 10, 10, 10), 1000)
@@ -164,8 +164,8 @@ linear_index = sub2ind ([3, 3], 2, 3)\n\
 
 ## Test input validation
 %!error <dimension vector> sub2ind ([10 10.5], 1, 1)
-%!error <subscript indices> sub2ind ([10 10], 1.5, 1)
-%!error <subscript indices> sub2ind ([10 10], 1, 1.5)
+%!error <Accessing index 1.5> sub2ind ([10 10], 1.5, 1)
+%!error <Accessing index 1.5> sub2ind ([10 10], 1, 1.5)
 */
 
 DEFUN (ind2sub, args, nargout,
diff --git a/liboctave/array/Array-util.cc b/liboctave/array/Array-util.cc
index 26ab018..c1a9cdb 100644
--- a/liboctave/array/Array-util.cc
+++ b/liboctave/array/Array-util.cc
@@ -178,7 +178,7 @@ octave_idx_type
 compute_index (octave_idx_type n, const dim_vector& dims)
 {
   if (n < 0)
-    gripe_invalid_index ();
+    gripe_invalid_index (n);
   if (n >= dims.numel ())
     gripe_index_out_of_range (1, 1, n+1, dims.numel ());
 
@@ -188,8 +188,10 @@ compute_index (octave_idx_type n, const dim_vector& dims)
 octave_idx_type
 compute_index (octave_idx_type i, octave_idx_type j, const dim_vector& dims)
 {
-  if (i < 0 || j < 0)
-    gripe_invalid_index ();
+  if (i < 0)
+    gripe_invalid_index (i);
+  else if (j < 0)
+    gripe_invalid_index (j);
   if (i >= dims(0))
     gripe_index_out_of_range (2, 1, i+1, dims(0));
   if (j >= dims.numel (1))
@@ -202,8 +204,12 @@ octave_idx_type
 compute_index (octave_idx_type i, octave_idx_type j, octave_idx_type k,
                const dim_vector& dims)
 {
-  if (i < 0 || j < 0 || k < 0)
-    gripe_invalid_index ();
+  if (i < 0)
+    gripe_invalid_index (i);
+  else if (j < 0)
+    gripe_invalid_index (j);
+  else if (k < 0)
+    gripe_invalid_index (k);
   if (i >= dims(0))
     gripe_index_out_of_range (3, 1, i+1, dims(0));
   if (j >= dims(1))
@@ -222,7 +228,7 @@ compute_index (const Array<octave_idx_type>& ra_idx, const dim_vector& dims)
   for (int d = 0; d < nd; d++)
     {
       if (ra_idx(d) < 0)
-        gripe_invalid_index ();
+        gripe_invalid_index (ra_idx(d));
       if (ra_idx(d) >= dv(d))
         gripe_index_out_of_range (nd, d+1, ra_idx(d)+1, dv(d));
     }
diff --git a/liboctave/array/Array.cc b/liboctave/array/Array.cc
index 882ba59..8c49b7e 100644
--- a/liboctave/array/Array.cc
+++ b/liboctave/array/Array.cc
@@ -190,7 +190,7 @@ Array<T>::checkelem (octave_idx_type n)
 {
   // Do checks directly to avoid recomputing slice_len.
   if (n < 0)
-    gripe_invalid_index ();
+    gripe_invalid_index (n);
   if (n >= slice_len)
     gripe_index_out_of_range (1, 1, n+1, slice_len);
 
@@ -224,7 +224,7 @@ Array<T>::checkelem (octave_idx_type n) const
 {
   // Do checks directly to avoid recomputing slice_len.
   if (n < 0)
-    gripe_invalid_index ();
+    gripe_invalid_index (n);
   if (n >= slice_len)
     gripe_index_out_of_range (1, 1, n+1, slice_len);
 
@@ -1180,7 +1180,7 @@ Array<T>::assign (const idx_vector& i, const Array<T>& rhs, const T& rfv)
         }
     }
   else
-    gripe_invalid_assignment_size ();
+    gripe_nonconformant ("=", dim_vector(i.length(n),1), rhs.dims());
 }
 
 template <class T>
@@ -1282,7 +1282,7 @@ Array<T>::assign (const idx_vector& i, const idx_vector& j,
         }
     }
   else
-    gripe_assignment_dimension_mismatch ();
+    gripe_nonconformant ("=", il, jl, rhs.dim1(), rhs.dim2());
 }
 
 template <class T>
@@ -1384,10 +1384,18 @@ Array<T>::assign (const Array<idx_vector>& ia,
             }
         }
       else
-        gripe_assignment_dimension_mismatch ();
+	gripe_nonconformant  ("=", dv, rhdv);
     }
 }
 
+/*
+%!shared a
+%! a = [1 2; 3 4];
+%!error <op1 is 1x2, op2 is 1x3> a(1,:) = [1 2 3]
+%!error <op1 is 2x1, op2 is 1x3> a(:,1) = [1 2 3]
+%!error <op1 is 2x2, op2 is 2x1> a(1:2,2:3) = [1;2]
+*/
+
 template <class T>
 void
 Array<T>::delete_elements (const idx_vector& i)
diff --git a/liboctave/array/Sparse.cc b/liboctave/array/Sparse.cc
index c861d3e..f6f7475 100644
--- a/liboctave/array/Sparse.cc
+++ b/liboctave/array/Sparse.cc
@@ -1978,7 +1978,7 @@ Sparse<T>::assign (const idx_vector& idx, const Sparse<T>& rhs)
         assign (idx, Sparse<T> (rhl, 1));
     }
   else
-    gripe_invalid_assignment_size ();
+    gripe_nonconformant ("=", dim_vector(idx.length (n),1), rhs.dims());
 }
 
 template <class T>
@@ -2214,7 +2214,7 @@ Sparse<T>::assign (const idx_vector& idx_i,
         assign (idx_i, idx_j, Sparse<T> (n, m));
     }
   else
-    gripe_assignment_dimension_mismatch ();
+    gripe_nonconformant  ("=", idx_i.length (nr), idx_j.length (nc), n, m);
 }
 
 // Can't use versions of these in Array.cc due to duplication of the
diff --git a/liboctave/array/idx-vector.cc b/liboctave/array/idx-vector.cc
index a5fc261..2d4e70e 100644
--- a/liboctave/array/idx-vector.cc
+++ b/liboctave/array/idx-vector.cc
@@ -113,9 +113,14 @@ idx_vector::idx_range_rep::idx_range_rep (octave_idx_type _start,
       gripe_invalid_range ();
       err = true;
     }
-  else if (start < 0 || (step < 0 && start + (len-1)*step < 0))
+  else if (start < 0)
     {
-      gripe_invalid_index ();
+      gripe_invalid_index (start);
+      err = true;
+    }
+  else if (step < 0 && start + (len-1)*step < 0)
+    {
+      gripe_invalid_index (start + (len-1)*step);
       err = true;
     }
 }
@@ -134,15 +139,23 @@ idx_vector::idx_range_rep::idx_range_rep (const Range& r)
         {
           start = static_cast<octave_idx_type> (r.base ()) - 1;
           step = static_cast<octave_idx_type> (r.inc ());
-          if (start < 0 || (step < 0 && start + (len-1)*step < 0))
+          if (start < 0)
+            {
+              gripe_invalid_index (start);
+              err = true;
+            }
+          else if (step < 0 && start + (len-1)*step < 0)
             {
-              gripe_invalid_index ();
+              gripe_invalid_index (start + (len-1)*step);
               err = true;
             }
         }
       else
         {
-          gripe_invalid_index ();
+	  // find first non-integer, then gripe about it
+	  double b = r.base();
+	  double inc = r.inc();
+          gripe_invalid_index (b != floor(b) ? b : b+inc);
           err = true;
         }
     }
@@ -221,7 +234,11 @@ convert_index (octave_idx_type i, bool& conv_error,
                octave_idx_type& ext)
 {
   if (i <= 0)
-    conv_error = true;
+    {
+      if (!conv_error)		// only gripe once, for things like A(-10000:0)
+        gripe_invalid_index (i-1);
+      conv_error = true;
+    }
 
   if (ext < i)
     ext = i;
@@ -235,7 +252,10 @@ convert_index (double x, bool& conv_error, octave_idx_type& ext)
   octave_idx_type i = static_cast<octave_idx_type> (x);
 
   if (static_cast<double> (i) != x)
-    conv_error = true;
+    {
+      gripe_invalid_index (x-1);
+      conv_error = true;
+    }
 
   return convert_index (i, conv_error, ext);
 }
@@ -264,9 +284,6 @@ idx_vector::idx_scalar_rep::idx_scalar_rep (T x)
   octave_idx_type dummy = 0;
 
   data = convert_index (x, err, dummy);
-
-  if (err)
-    gripe_invalid_index ();
 }
 
 idx_vector::idx_scalar_rep::idx_scalar_rep (octave_idx_type i)
@@ -274,7 +291,7 @@ idx_vector::idx_scalar_rep::idx_scalar_rep (octave_idx_type i)
 {
   if (data < 0)
     {
-      gripe_invalid_index ();
+      gripe_invalid_index (data);
       err = true;
     }
 }
@@ -327,10 +344,7 @@ idx_vector::idx_vector_rep::idx_vector_rep (const Array<T>& nda)
       data = d;
 
       if (err)
-        {
-          delete [] data;
-          gripe_invalid_index ();
-        }
+        delete [] data;
     }
 }
 
@@ -347,15 +361,16 @@ idx_vector::idx_vector_rep::idx_vector_rep (const Array<octave_idx_type>& inda)
         {
           octave_idx_type k = inda.xelem (i);
           if (k < 0)
-            err = true;
+	    {
+	      if (!err)		// only report first error, in case 1000s.
+		gripe_invalid_index (k);
+              err = true;
+	    }
           else if (k > max)
             max = k;
         }
 
       ext = max + 1;
-
-      if (err)
-        gripe_invalid_index ();
     }
 }
 
@@ -459,7 +474,7 @@ idx_vector::idx_vector_rep::checkelem (octave_idx_type n) const
 {
   if (n < 0 || n >= len)
     {
-      gripe_invalid_index ();
+      gripe_invalid_index (n);
       return 0;
     }
 
@@ -709,7 +724,7 @@ idx_vector::idx_mask_rep::checkelem (octave_idx_type n) const
 {
   if (n < 0 || n >= len)
     {
-      gripe_invalid_index ();
+      gripe_invalid_index (n);
       return 0;
     }
 
diff --git a/liboctave/util/lo-array-gripes.cc b/liboctave/util/lo-array-gripes.cc
index 7e476bc..8867428 100644
--- a/liboctave/util/lo-array-gripes.cc
+++ b/liboctave/util/lo-array-gripes.cc
@@ -129,16 +129,24 @@ gripe_del_index_out_of_range (bool is1d, octave_idx_type idx,
 }
 
 void
-gripe_invalid_index (void)
+gripe_invalid_index (octave_idx_type n)
+{
+    gripe_invalid_index (static_cast<double> (n));
+}
+
+void
+gripe_invalid_index (double n)
 {
   const char *err_id = error_id_invalid_index;
 
   (*current_liboctave_error_with_id_handler)
+    (err_id, "Accessing index %g. Subscript indices must be either integers between 1 and "
 #ifdef USE_64_BIT_IDX_T
-    (err_id, "subscript indices must be either positive integers less than 2^63 or logicals");
+    "2^63"
 #else
-    (err_id, "subscript indices must be either positive integers less than 2^31 or logicals");
+    "2^31"
 #endif
+    " or logicals", n+1);
 }
 
 // FIXME: the following is a common error message to resize,
@@ -157,20 +165,6 @@ gripe_invalid_resize (void)
 }
 
 void
-gripe_invalid_assignment_size (void)
-{
-  (*current_liboctave_error_handler)
-    ("A(I) = X: X must have the same size as I");
-}
-
-void
-gripe_assignment_dimension_mismatch (void)
-{
-  (*current_liboctave_error_handler)
-    ("A(I,J,...) = X: dimensions mismatch");
-}
-
-void
 gripe_singular_matrix (double rcond)
 {
   if (rcond == 0.0)
diff --git a/liboctave/util/lo-array-gripes.h b/liboctave/util/lo-array-gripes.h
index 6b9c85d..da2867d 100644
--- a/liboctave/util/lo-array-gripes.h
+++ b/liboctave/util/lo-array-gripes.h
@@ -64,16 +64,13 @@ gripe_del_index_out_of_range (bool is1d, octave_idx_type iext,
                               octave_idx_type ext);
 
 extern void OCTAVE_API
-gripe_invalid_index (void);
+gripe_invalid_index (double);
 
 extern void OCTAVE_API
-gripe_invalid_resize (void);
-
-extern void OCTAVE_API
-gripe_invalid_assignment_size (void);
+gripe_invalid_index (octave_idx_type n);
 
 extern void OCTAVE_API
-gripe_assignment_dimension_mismatch (void);
+gripe_invalid_resize (void);
 
 extern void OCTAVE_API
 gripe_singular_matrix (double rcond = 0.0);
