Is this string valid FEN?
JavaScript (ES6), 168 174 ... 155

This answer has been edited an embarrassing number of times. Hopefully, the current version is both reliable and decently golfed.



Returns a boolean.

s=&gt;[...s].map(c=&gt;++n%9?+c?n+=--c:a[i='pP/KkQqRrBbNn'.search(c),i&amp;=i&gt;4&amp;a[i]&gt;(i&gt;6)||i]=-~a[i]:x+=c=='/',a=[x=n=0])&amp;&amp;!([p,P,s,k,K]=a,n-71|x-7|s|k*K-1|p&gt;8|P&gt;8)


Formatted and commented

s =&gt; [...s].map(c =&gt;                  // for each character 'c' in the FEN string 's':
  ++n % 9 ?                           //   if we haven't reached the end of a rank:
    +c ?                              //     if the character is a digit:
      n += --c                        //       advance the board pointer by c - 1 squares
    :                                 //     else:
      a[                              //       update the piece counter array:
        i =                           //         i = piece identifier (0 to 12)
          'pP/KkQqRrBbNn'.search(c),  //             with special case: '/' --&gt; 2
        i &amp;=                          //         we count it as a promoted pawn instead if:
          i &gt; 4 &amp;                     //           it's a Q, R, B or N and we already have
          a[i] &gt; (i &gt; 6) ||           //           2 of them for R, B, N or just 1 for Q
          i                           //           else, we keep the identifier unchanged
      ] = -~a[i]                      //         '-~' allows to increment 'undefined'
  :                                   //   else:
    x += c == '/',                    //     check that the expected '/' is there
  a = [                               //   initialize the piece counter array 'a'
    x =                               //   initialize the '/' counter 'x',
    n = 0 ]                           //   initialize the board pointer 'n'
) &amp;&amp;                                  // end of map()
!(                                    // now it's time to perform all sanity checks:
  [p, P, s, K, k] = a,                //   copy the 5 first entries of 'a' to new variables
  n - 71 |                            //   have we reached exactly the end of the board?
  x - 7 |                             //   have we identified exactly 7 ends of rank?
  s |                                 //   have we encountered any unexpected '/' character?
  k * K - 1 |                         //   do we have exactly one king on each side?
  p &gt; 8 |                             //   no more than 8 black pawns, including promotions?
  P &gt; 8)                              //   no more than 8 white pawns, including promotions?


Test cases



let f =

s=&gt;[...s].map(c=&gt;++n%9?+c?n+=--c:a[i='pP/KkQqRrBbNn'.search(c),i&amp;=i&gt;4&amp;a[i]&gt;(i&gt;6)||i]=-~a[i]:x+=c=='/',a=[x=n=0])&amp;&amp;!([p,P,s,k,K]=a,n-71|x-7|s|k*K-1|p&gt;8|P&gt;8)

console.log(f("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR")) // True
console.log(f("2br2k1/1p2n1q1/p2p2p1/P1bP1pNp/1BP2PnP/1Q1B2P1/8/3NR2K")) // True
console.log(f("r2r2k1/p3q2p/ppR3pr/rP4bp/3p4/5B1P/P4PP1/3Q1RK1")) // False (black has 7 pawns and 4 rooks - impossible)
console.log(f("6k1/pp3ppp/4p3/2P3b1/bPP3P1/3K4/P3Q1q1")) // False (only 7 ranks)
console.log(f("3r1rk1/1pp1bpp1/6p1/pP1npqPn/8/4N2P/P2PP3/1B2BP2/R2QK2R")) // False (9 ranks)
console.log(f("5n1k/1p3r1qp/p3p3/2p1N2Q/2P1R3/2P5/P2r1PP1/4R1K1")) // False (2nd rank has 9 squares/pieces)
console.log(f("rnbqkbnr/pppppppp/8/35/8/8/PPPPPPPP/RNBQKBNR")) // True
console.log(f("rnbqkbnr/pppppppp/8/9/7/8/PPPPPPPP/RNBQKBNR")) // False (additional test case suggested by Rick Hitchcock)
console.log(f("rnbqkbnr/pppp/ppp/8/8/8/8/PPPPPPPP/RNBQKBNR")) // False (additional test case)